/* Transcripts — shared component layer.

   Everything used by more than one document lives here; page-specific CSS stays in the
   page's own <style>, which is linked AFTER this file so it can extend these rules.
   Reads tokens from css/tokens.css and declares no colour, size or radius of its own —
   test/design-tokens.test.js fails on a raw hex or a raw font-size px in this file. */

*{box-sizing:border-box; -webkit-tap-highlight-color:transparent;}
html,body{margin:0; padding:0;}
[hidden]{display:none !important;}

body{
  font-family:'Spline Sans','Noto Sans Hebrew','Noto Sans Arabic',system-ui,sans-serif;
  background:var(--bg); color:var(--ink);
  line-height:var(--leading-ui); font-size:var(--text-md);
  -webkit-font-smoothing:antialiased;
}
.mono{font-family:'Spline Sans Mono',monospace;}

/* Keyboard focus is visible on every interactive element, once, from the token.
   :focus-visible (not :focus) so a pointer press does not paint a ring. */
:where(a, button, input, select, textarea, [tabindex]):focus-visible{
  outline:2px solid var(--brand); outline-offset:2px; border-radius:var(--radius-sm);
}

/* ------------------------------------------------------------------ logo mark
   Five bars — rise, dip, peak, partial fall. A waveform, not a pyramid.

   --logo-h IS the mark: bar 4 is the full height by definition and the other four are
   fractions of it, so a call site sets one number and the silhouette scales intact.
   The heights used to be inline-styled at seven call sites plus scripts/make-icons.js
   with only the colour shared, which is how a shape change turns into a seven-file hunt.
   test/logo-mark.test.js pins these ratios against the icon script's BARS array. */
.logo{display:flex; align-items:flex-end; gap:3px; --logo-h:22px; height:var(--logo-h);}
.logo span{width:4px; border-radius:2px; background:var(--brand);}
.logo span:nth-child(1){height:calc(var(--logo-h) * .36);}
.logo span:nth-child(2){height:calc(var(--logo-h) * .64);}
.logo span:nth-child(3){height:calc(var(--logo-h) * .50);}
/* Bar 4 is the apex and the one warm note in the identity. Both, always, together. */
.logo span:nth-child(4){height:var(--logo-h); background:var(--zest);}
.logo span:nth-child(5){height:calc(var(--logo-h) * .73);}

/* --------------------------------------------------------------------- button */
.btn{
  font-family:inherit; font-size:var(--text-md); font-weight:var(--weight-medium);
  border-radius:var(--radius-control); border:1px solid var(--line);
  background:var(--surface); color:var(--ink); min-height:44px; padding:11px 16px; cursor:pointer;
  display:inline-flex; align-items:center; gap:var(--space-2); justify-content:center;
}
/* Ink fill: destructive confirmation and modal commit. --brand-fill is the primary now. */
.btn.primary{background:var(--ink); color:var(--on-brand); border-color:var(--ink);}
/* The primary action. --brand-fill, never --brand: white on --brand is only 3.7:1. */
.btn.accent{background:var(--brand-fill); color:var(--on-brand); border-color:var(--brand-fill);}
.btn.block{width:100%;}
.btn svg{width:17px; height:17px;}
.btn:disabled{opacity:var(--disabled-opacity); cursor:default;}
.btn.ghost{background:transparent; border-color:transparent; color:var(--muted); padding:8px 10px;}

/* A press is answered, always. Line 8 suppresses the platform's native tap flash on every
   element and touch has no :hover to fall back on, so :active is the ONLY feedback a
   finger ever receives — a control without it is unfinished. Declared AFTER the variants:
   .btn.primary and .btn:active tie on specificity, so an earlier press rule would lose to
   the variant's own background and the filled buttons would go dead again. */
.btn:active,
.seg button:active,
.btnrow button:active,
.linkbtn:active{background:var(--surface-pressed);}
.btn.primary:active{background:var(--ink-fill-hover);}
.btn.accent:active{background:var(--brand-fill-hover); border-color:var(--brand-fill-hover);}
.btn:disabled:active{background:var(--surface); transform:none;}
.btn.primary:disabled:active{background:var(--ink);}
.btn.accent:disabled:active{background:var(--brand-fill);}
.btn:active{transform:translateY(1px);}
.btn,.iconbtn,.star,.seg button{
  transition:background var(--dur-fast), border-color var(--dur-fast), color var(--dur-fast), box-shadow var(--dur-fast);
}

/* ------------------------------------------------------------ input / select */
input[type=password],input[type=text],input[type=email],input[type=number],input[type=search],textarea{
  width:100%; font-family:inherit; font-size:var(--text-md); padding:12px 13px;
  border:1px solid var(--line); border-radius:var(--radius-control);
  background:var(--surface); color:var(--ink);
}
input:focus,textarea:focus{outline:none; border-color:var(--brand); box-shadow:var(--focus-ring);}
label.fld{
  display:block; font-size:var(--text-sm); font-weight:var(--weight-semi); color:var(--muted);
  text-transform:uppercase; margin:var(--space-4) 0 7px;
}

/* Segmented control — a single-choice radio group. It is NOT a container for a pair of
   unrelated commands; use .btnrow for those. Selection is carried by aria-checked, so the
   accessible state and the painted state cannot drift apart. */
.seg{
  display:flex; gap:6px; background:var(--surface-sunk); padding:5px;
  border-radius:var(--radius-control); border:1px solid var(--line);
}
.seg button{
  flex:1; font-family:inherit; font-size:var(--text-base); font-weight:var(--weight-medium);
  border:0; background:transparent; padding:9px 6px; border-radius:var(--radius-sm);
  cursor:pointer; color:var(--muted); line-height:var(--leading-tight); min-height:44px;
}
/* This used to raise a --surface pill on the --surface-sunk track. That inverts on dark,
   where --surface is DARKER than the track it sits on and --shadow-sm is a black shadow on
   a dark ground — so "selected" read as a recess and was carried by the text colour alone.
   The brand trio is what .setnavitem and the speaker list already use, and it separates in
   both themes. Inset box-shadow rather than a border, so selecting does not shift the pill
   by a pixel. */
.seg button[aria-checked="true"]{
  background:var(--selected-bg); color:var(--selected-ink);
  box-shadow:inset 0 0 0 1px var(--selected-line); font-weight:var(--weight-semi);
}
.seg button[aria-checked="true"] small{color:var(--selected-ink); opacity:.8;}
/* The checked rule and the generic press rule both score (0,2,1) and this one is declared
   later, so without its own press the SELECTED option is the single control in the group
   that stays silent under a finger. --selected-line is the same brand at a heavier weight,
   so the press reads as "more of the same colour" rather than a different idea. */
.seg button[aria-checked="true"]:active{background:var(--selected-line);}
.seg button small{
  display:block; font-weight:var(--weight-normal); font-size:var(--text-xs);
  color:var(--faint); margin-top:1px;
}

/* A row of independent commands. The segmented control kept getting borrowed for these —
   a confirm/cancel pair, a set/remove pair — and its children can never take a selected
   state, so they inherited .seg button's transparent, hover-less, press-less styling and
   were visually dead. Real .btn children, so they answer a press like every other button. */
.btnrow{display:flex; gap:var(--space-2);}
.btnrow > .btn{flex:1;}
.btnrow > .btn.compact{flex:0 0 auto;}

/* A value and its one action sharing a sunk track — a share input and its Share, a grantee
   and its Revoke. This was the segmented control's third borrowed job. The action is a real
   .btn so it reads as pressable against the track and answers a press. */
.fieldrow{
  display:flex; gap:6px; align-items:center; background:var(--surface-sunk); padding:5px;
  border-radius:var(--radius-control); border:1px solid var(--line);
}
.fieldrow > input{
  flex:1; min-width:0; background:transparent; border:0; color:inherit; font:inherit;
  padding:10px; min-height:44px;
}
/* The track carries focus, not the borderless input inside it — same shape as
   .searchrow:focus-within. Never leave the input's own indicator suppressed with
   nothing put back: that is how the language select lost its ring. */
.fieldrow:focus-within{border-color:var(--brand); box-shadow:var(--focus-ring);}
.fieldrow > input:focus{outline:none; border:0; box-shadow:none;}
.fieldrow > .label{
  flex:1; min-width:0; padding:10px; overflow:hidden;
  text-overflow:ellipsis; white-space:nowrap;
}
.fieldrow > .btn{flex:0 0 auto;}

/* ----------------------------------------------------------------------- card */
.card{
  background:var(--surface); border:1px solid var(--line); border-radius:var(--radius-card);
  padding:16px 16px 14px; margin-top:14px; box-shadow:var(--shadow-sm);
}
.hint{font-size:var(--text-sm); color:var(--muted); margin-top:var(--space-2); line-height:1.5;}
.hint a{color:var(--brand-deep);}
/* Section micro-label. No tracking: uppercase Latin wants it, Arabic and Persian break
   under it, and this label carries translated copy. */
.sectlabel,.lbl{
  font-size:var(--text-xs); text-transform:uppercase; color:var(--faint);
  font-weight:var(--weight-semi);
}
.sectlabel{margin:26px 4px 2px;}
.lbl{margin-bottom:var(--space-2);}

/* Notice banner. Class name is historical (.banner) — js/ and test/ select on it. */
.banner{
  background:var(--notice-bg); border:1px solid var(--notice-line); color:var(--notice-ink);
  border-radius:var(--radius-control); padding:11px 14px; font-size:var(--text-base);
  margin-top:14px; display:flex; gap:9px; align-items:flex-start;
}
.banner svg{width:16px; height:16px; flex:none; margin-top:1px;}

/* -------------------------------------------------- transcript content blocks
   Shared by the app reader and the public shared-transcript page. */
.heb{
  font-family:'Noto Sans Hebrew','Noto Sans Arabic','Spline Sans',sans-serif; direction:rtl; text-align:right;
  font-size:var(--text-lg); line-height:1.85; color:var(--ink);
  white-space:pre-wrap; word-break:break-word;
}
.heb p{margin:0 0 10px; white-space:pre-wrap;}
.heb p:last-child{margin-bottom:0;}
.turn{margin-bottom:var(--turn-gap);}
.turn:last-child{margin-bottom:0;}
/* Speaker names were green identity text. Green now means "synced", so the name is
   plain ink weight 700, identified by a brand dot instead of by colour. */
.spk{
  display:block; font-weight:var(--weight-bold); color:var(--ink);
  font-size:var(--text-base); margin-bottom:6px;
}
.spk::before{
  content:""; display:inline-block; width:6px; height:6px; border-radius:50%;
  background:var(--brand); margin-inline-end:var(--space-2); vertical-align:middle;
}

/* ------------------------------------------------------- sheet / scrim / toast */
.scrim{
  position:fixed; inset:0; background:var(--scrim); z-index:var(--z-scrim);
  opacity:0; pointer-events:none; transition:opacity .2s;
}
.scrim.on{opacity:1; pointer-events:auto;}
.sheet{
  position:fixed; inset-inline:0; bottom:0; z-index:var(--z-sheet); background:var(--bg);
  border-radius:var(--radius-sheet) var(--radius-sheet) 0 0;
  padding:var(--space-2) 18px calc(22px + env(safe-area-inset-bottom));
  transform:translateY(102%); transition:transform var(--dur-base) var(--ease-out);
  max-width:640px; margin:0 auto; box-shadow:var(--shadow-sheet);
}
.sheet.on{transform:translateY(0);}
.sheet.scroll{max-height:min(88vh,760px); overflow-y:auto;}
.grip{width:38px; height:4px; border-radius:2px; background:var(--line-strong); margin:6px auto 14px;}
.sheet h2{font-size:var(--text-lg); margin:0 0 4px; font-weight:var(--weight-semi);}
.sheet .lead{color:var(--muted); font-size:var(--text-base); margin:0 0 18px;}
.toast{
  position:fixed; left:50%; bottom:calc(26px + env(safe-area-inset-bottom));
  transform:translateX(-50%) translateY(20px);
  background:var(--ink); color:var(--bg); padding:11px 18px; border-radius:var(--radius-pill);
  font-size:var(--text-base); z-index:var(--z-toast); opacity:0; pointer-events:none;
  transition:opacity .2s, transform .2s; box-shadow:var(--shadow-dialog);
}
.toast.on{opacity:1; transform:translateX(-50%) translateY(0);}
/* An action on the toast (Undo after a voice was remembered). The toast itself ignores the
   pointer so a fading one never blocks a tap beneath it; the button must take it back, with
   a hit area grown into the toast's own padding rather than a taller toast. */
.toast .toast-action{
  pointer-events:auto; margin:-8px -6px -8px 12px; padding:8px 6px; min-height:40px;
  background:none; border:0; color:inherit; font:inherit; font-weight:var(--weight-semi);
  text-decoration:underline; text-underline-offset:3px; cursor:pointer; border-radius:var(--radius-pill);
}
.toast .toast-action:active{opacity:.6; transform:scale(.96);}
.toast .toast-action:focus-visible{outline:2px solid var(--bg); outline-offset:-2px;}

/* ------------------------------------------------------------- centred auth box
   Shared by login.html and the in-app upgrade gate. The .login* names are historical. */
.loginbox{width:100%; max-width:360px;}
.logintitle{font-size:var(--text-xl); font-weight:var(--weight-semi); margin:18px 0 2px; text-align:center;}
.loginsub{color:var(--muted); font-size:var(--text-base); margin:0 0 18px; text-align:center;}
.loginerr{
  color:var(--danger); font-size:var(--text-base); margin-top:var(--space-3);
  min-height:1.2em; text-align:center; display:none;
}
.loginerr.on{display:block;}
.loginlinks{display:flex; justify-content:space-between; margin-top:var(--space-4);}
.linkbtn{
  background:none; border:none; padding:0; color:var(--muted); font-size:var(--text-base);
  cursor:pointer; text-decoration:underline; text-underline-offset:3px;
}
.linkbtn:hover{color:var(--ink);}

/* -------------------------------------------------- policy call to action
   The link out of a policy summary and into the page that owns the subject. It is a
   button, not a text link, because the audit hit-tests it at every width and a 19px
   inline anchor inside a card is unreachable on a phone. */
.policyCta{
  display:inline-flex; align-items:center; min-height:44px; margin-block-start:var(--space-4);
  padding-inline:14px; border:1px solid var(--brand-fill); border-radius:10px;
  background:var(--brand-fill); color:var(--on-brand);
  font-size:var(--text-base); font-weight:var(--weight-semi);
}

/* ------------------------------------------------------------ feedback widget
   The anonymous report form, shared by the landing page and /support. Behaviour is in
   shared/feedback.js; the markup contract is the fb* ids. */
/* Above the sticky header's z-index so it stays reachable at any scroll position.
   inset-inline-end rather than right: the logical-property rule is enforced across the
   whole stylesheet and an exception here would be the one that rots. */
/* 44px, not 40: it is a floating target and the audit hit-tests it at every width. */
.fbBtn{
  position:fixed; z-index:var(--z-scrim); inset-inline-end:18px;
  bottom:calc(18px + env(safe-area-inset-bottom));
  display:inline-flex; align-items:center; gap:8px; min-height:44px;
  background:var(--surface); color:var(--ink); border:1px solid var(--line);
  border-radius:var(--radius-pill); padding:10px 16px; cursor:pointer;
  font-family:inherit; font-size:var(--text-base); font-weight:var(--weight-semi);
  box-shadow:var(--shadow-card);
}
.fbPanel{
  position:fixed; z-index:calc(var(--z-scrim) + 1); inset-inline-end:18px;
  bottom:calc(68px + env(safe-area-inset-bottom));
  /* Never wider than the viewport minus the gutter it sits in — on a 320px phone the
     fixed 300px card would otherwise hang off the inline edge. */
  width:min(300px, calc(100vw - 36px));
  background:var(--surface); border:1px solid var(--line); border-radius:16px;
  box-shadow:var(--shadow-card); padding:var(--space-4); text-align:start;
  visibility:hidden; opacity:0; transform:translateY(6px);
  transition:opacity .18s ease, transform .18s ease, visibility .18s;
}
.fbPanel.on{visibility:visible; opacity:1; transform:none;}
.fbPanel h3{margin:0 0 10px; font-size:var(--text-md); font-weight:var(--weight-semi);}
.fbPanel textarea, .fbPanel input{
  width:100%; font-family:inherit; font-size:var(--text-base); color:var(--ink);
  background:var(--bg); border:1px solid var(--line); border-radius:10px;
  padding:9px 10px; margin-block-end:8px;
}
.fbPanel textarea{min-height:84px; resize:vertical;}
.fbSend{
  width:100%; min-height:40px; font-family:inherit;
  font-size:var(--text-base); font-weight:var(--weight-semi);
  color:var(--on-brand); background:var(--brand-fill); border:1px solid var(--brand-fill);
  border-radius:11px; cursor:pointer;
}
.fbSend[disabled]{opacity:.5; cursor:default;}
.fbClose{
  position:absolute; inset-inline-end:8px; top:8px; width:28px; height:28px;
  display:inline-flex; align-items:center; justify-content:center; border-radius:var(--radius-sm);
  background:none; border:0; color:var(--faint); font-size:var(--text-lg); cursor:pointer;
}
.fbNote{margin:8px 0 0; font-size:var(--text-sm); color:var(--faint); min-height:1.2em;}
/* Not behind (hover:hover): these surfaces are read on a phone more than anywhere else,
   and a tap there has no hover to fall back on. */
.fbBtn:active,.fbClose:active{background:var(--surface-pressed);}
.policyCta:active,.fbSend:active{background:var(--brand-fill-hover); border-color:var(--brand-fill-hover);}
.fbSend[disabled]:active{background:var(--brand-fill);}
@media (prefers-reduced-motion:reduce){
  .fbPanel{transition:none;}
}

/* Hover is the pointer's affordance; :active above is the one every device gets. Each is
   :not(:active) because the hover block is declared last and ties with the press rules on
   specificity — without it, hovering while pressing would repaint the hover colour and a
   mouse press would look like nothing happened. The accent and ghost variants used to live
   only in index.html's own copy of this block, so login.html and shared.html shipped an
   accent button with no hover at all. */
@media (hover:hover){
  .btn:hover:not(:active){background:var(--surface-hover);}
  .btn.primary:hover:not(:active){background:var(--ink-fill-hover);}
  .btn.accent:hover:not(:active){background:var(--brand-fill-hover); border-color:var(--brand-fill-hover);}
  .btn.ghost:hover:not(:active){background:var(--surface-hover); color:var(--ink);}
  .btn:disabled:hover{background:var(--surface);}
  .btn.primary:disabled:hover{background:var(--ink);}
  .btn.accent:disabled:hover{background:var(--brand-fill);}
  .seg button:hover:not(:active):not([aria-checked="true"]){background:var(--surface-hover);}
  .btnrow > .btn:hover:not(:active){background:var(--surface-hover);}
}
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    scroll-behavior:auto!important; transition-duration:.01ms!important;
    animation-duration:.01ms!important; animation-iteration-count:1!important;
  }
}
