/* ══════════════════════════════════════════════════════════════════════
   assets/site.css — THE SHARED SHELL for noamvardi.co.il
   Loaded by / and /lessons AFTER each page's own <style>, so the shell wins
   where the two overlap (header, TOC sheet, motion) and the page keeps
   everything else.

   What lives here, and nothing else:
     1. motion tokens        — one vocabulary for both pages
     2. the sticky top bar   — same bar, same height, same behaviour on both
     3. anchor offsets       — scroll-padding tied to the real bar height
     4. the TOC / menu sheet — base + motion (shared component)
     5. the accordion helper — grid-rows 0fr→1fr, no display:none snap
     6. button feel          — hover / press / busy
     7. reduced motion       — everything above, off

   Laws it obeys (design-final/Handoff-Final.md §3): radius 0 / 6 / 999,
   1.5px rules, cobalt is press-only, no shadows (the sheet excepted), no
   blur-glass, no scroll reveals, nothing waits on JS to become visible.
   ════════════════════════════════════════════════════════════════════ */

:root{
  /* Motion. Three durations, one easing. If a transition needs a fourth
     duration, the interaction is probably doing too much. */
  --m-fast:140ms;      /* hover, focus, pressed — the pointer's own feedback */
  --m-std:200ms;       /* state changes: chips, steps, menu, errors */
  --m-section:320ms;   /* drawers, accordions, a whole panel arriving */
  --ease-out:cubic-bezier(.22,.7,.28,1);

  /* The real height of the sticky bar. JS measures it and overwrites this;
     these fallbacks are what a no-JS visitor gets, and they are close. */
  --hdr:74px;
}
@media (min-width:769px){ :root{ --hdr:82px } }

/* Anchor navigation: the bar never lands on top of the target.
   ONE mechanism only — scroll-padding on the scroller. Both pages carry
   `scroll-margin-top:90px` of their own, and the two ADD UP: the target
   used to stop a whole bar-height too low (88 + 88 measured). So the
   element-side margin is zeroed here and the padding follows the real bar. */
html{ scroll-padding-top:calc(var(--hdr) + 14px) }
.anchor,section,[id]{ scroll-margin-top:0 }
@media (prefers-reduced-motion:no-preference){ html{ scroll-behavior:smooth } }

/* position:sticky dies inside a scroll container, and `overflow-x:hidden`
   on <body> makes one. `clip` clips without scrolling, so the bar survives. */
@supports (overflow:clip){ body{ overflow-x:clip } }

/* ── 1. the sticky top bar ─────────────────────────────────────────────
   Sticky, not fixed: it occupies its own space, so it can never cover the
   first line of the page. Quiet at the top of the document (soft rule),
   settled once you have scrolled (ink rule). The height does not change. */
.site-header{
  position:sticky; top:0; z-index:30;
  background:var(--paper);
  border-bottom:1.5px solid var(--rule-soft);
  padding-top:env(safe-area-inset-top);
  transition:border-color var(--m-std) var(--ease-out);
}
.site-header[data-scrolled="1"]{ border-bottom-color:var(--ink) }
.site-header .wrap{
  padding-inline:max(var(--gutter),env(safe-area-inset-right),env(safe-area-inset-left));
}
/* One bar, one size, on both pages — a visitor moving between / and
   /lessons must not see the shell change shape under them. */
.site-header .wrap{ padding-block:14px }
.site-header .brand img{ width:30px; height:30px }
.site-header .brand .nm,.site-header .brand>span:not([class]){ font-size:21px }
@media (min-width:769px){
  .site-header .wrap{ padding-block:18px }
  .site-header .brand img{ width:34px; height:34px }
  .site-header .brand .nm,.site-header .brand>span:not([class]){ font-size:24px }
}

/* 320: the name and the menu label were wrapping, which made the bar 88px
   tall instead of 74 and cost two lines of the page. Smaller name, no
   breadcrumb — the <span class="vh"> alternative still names the page. */
@media (max-width:359px){
  .site-header .brand .nm,.site-header .brand>span:not([class]){ font-size:18px }
  .site-header .brand{ gap:8px }
  .menu-btn{ padding-inline:12px; font-size:13px }
}

/* The "/ שיעורים" breadcrumb is decorative (aria-hidden; the <span class="vh">
   carries it for assistive tech). Below 1024 it is what pushes the bar into a
   second line at the tightest widths, so it goes. */
@media (max-width:1023px){ .site-header .brand .crumb{ display:none } }

/* the 1px probe that tells the bar whether the page is at the top */
.hdr-sentinel{ height:1px; margin-bottom:-1px }

/* nav link underline — grows from the label, never from the whole cell */
.toc-nav a,.lnav a{ position:relative; transition:color var(--m-fast) var(--ease-out) }
.toc-nav a::after,.lnav a::after{
  content:""; position:absolute; inset-inline:10px; bottom:4px; height:1.5px;
  background:currentColor; transform:scaleX(0); transform-origin:center;
  transition:transform var(--m-std) var(--ease-out);
}
.toc-nav a:hover::after,.lnav a:hover::after,
.toc-nav a:focus-visible::after,.lnav a:focus-visible::after{ transform:scaleX(1) }
.toc-nav a[aria-current="true"],.lnav a[aria-current="true"]{ color:var(--cobalt) }
.toc-nav a[aria-current="true"]::after,.lnav a[aria-current="true"]::after{ transform:scaleX(1) }

/* the menu trigger: its own small state, so the tap registers */
.menu-btn{ transition:background-color var(--m-fast) var(--ease-out),color var(--m-fast) var(--ease-out),border-color var(--m-fast) var(--ease-out) }
.menu-btn[aria-expanded="true"]{ background:var(--ink); color:var(--paper); border-color:var(--ink) }

/* ── 2. the sheet (menu / TOC, ≤768) ───────────────────────────────────
   role="dialog", above the bar, entering from the edge it is docked to. */
.sheet-scrim{
  position:fixed; inset:0; background:rgba(22,22,26,.45); z-index:40;
  opacity:0; transition:opacity var(--m-std) var(--ease-out);
}
.sheet-scrim.is-open{ opacity:1 }
.sheet{
  position:fixed; inset-inline:0; bottom:0; z-index:50;
  background:var(--card); border-top:1.5px solid var(--ink);
  padding:20px var(--gutter) calc(24px + env(safe-area-inset-bottom));
  box-shadow:0 -20px 40px -20px rgba(22,22,26,.4);
  max-height:88vh; overflow:auto;
  transform:translateY(8%); opacity:0;
  transition:transform var(--m-std) var(--ease-out),opacity var(--m-fast) linear;
}
.sheet.is-open{ transform:none; opacity:1 }
.sheet.is-closing{ transition-duration:var(--m-fast) }
.sheet li a{ transition:color var(--m-fast) var(--ease-out) }
.sheet li a:hover{ color:var(--cobalt) }

/* ── 3. accordion ──────────────────────────────────────────────────────
   The panel is OPEN in the markup. JS collapses it, so a no-JS or
   failed-script visitor reads everything. Height animates via grid rows;
   nothing is display:none, nothing snaps. */
.acc{ display:grid; grid-template-rows:1fr; transition:grid-template-rows var(--m-section) var(--ease-out) }
.acc>*{ min-height:0; overflow:hidden; transition:visibility 0s }
.acc[data-open="false"]{ grid-template-rows:0fr }
/* a collapsed panel must also leave the tab order — visibility flips only
   once the fold has finished, so the content does not vanish mid-animation */
.acc[data-open="false"]>*{ visibility:hidden; transition:visibility 0s linear var(--m-section) }
.acc-trigger .caret{ display:inline-block; transition:transform var(--m-std) var(--ease-out) }
.acc-trigger[aria-expanded="true"] .caret{ transform:rotate(180deg) }

/* ── 4. buttons: hover shift, real press, honest busy ──────────────── */
.btn{ transition:background-color var(--m-fast) var(--ease-out),color var(--m-fast) var(--ease-out),border-color var(--m-fast) var(--ease-out),transform var(--m-fast) var(--ease-out) }
.btn:active:not([disabled]){ transform:translateY(1px) }
.btn[aria-busy="true"]{ cursor:progress }
.btn[aria-busy="true"] .dots::after{
  content:"·"; animation:shell-dots 1.2s steps(1,end) infinite;
}
@keyframes shell-dots{ 0%{content:"·"} 33%{content:"··"} 66%{content:"···"} }

/* ── 5. arrival emphasis on an anchor target ──────────────────────────
   A single soft wash in ink, once. Not cobalt: nothing here is pressable. */
@keyframes shell-arrive{ from{ background-color:rgba(22,22,26,.07) } to{ background-color:transparent } }
.is-arrived{ animation:shell-arrive var(--m-section) var(--ease-out) 1; border-radius:6px }

/* ── 6. reduced motion — everything above, instantly ──────────────── */
@media (prefers-reduced-motion:reduce){
  html{ scroll-behavior:auto }
  .acc>*,.acc[data-open="false"]>*{ transition-delay:0s!important }
  .site-header,.sheet,.sheet-scrim,.acc,.acc-trigger .caret,.btn,
  .toc-nav a,.toc-nav a::after,.lnav a,.lnav a::after,.menu-btn{
    transition-duration:.001ms!important;
  }
  .btn:active:not([disabled]){ transform:none }
  .is-arrived,.btn[aria-busy="true"] .dots::after{ animation:none!important }
}
