/* ============================================================
   Quadrant UI - design tokens + shared components (Phase 2)
   Evidence-based: WCAG 2.2 AA contrast + 44px targets, 4px
   spacing scale, 16px body, tabular right-aligned numbers,
   responsive table->card collapse, reduced-motion support.
   Additive: pages opt in by linking this file and using q-*
   classes. Nothing changes until a page adopts it.
   ============================================================ */

:root{
  /* color roles */
  /* --q-surface: the fill of cards, inputs, chips and tables. Third value
     this token has held, and this one is Rod's, decided 9 Aug 2026, so
     leave it alone without him: "I like the whole page to be the same
     color with just the boxes. More like the website."

     And that IS how the website works - styles/quadrant.css paints .qcard,
     .pain, .step and .magnet with background:var(--paper), the SAME
     #f3eee2 as the page, and a box is a box because of its 2px ink border
     and hard shadow, not because of a different fill. So surface now
     equals bg on purpose. The two prior values tell the history: #ffffff
     put foreign white boxes on the tan page, and #fbf8f0 was a repair
     that quietly recolored the whole app instead of matching the site. */
  --q-bg:#f3eee2; --q-surface:#f3eee2; --q-border:#d8cfba;
  --q-ink:#211f1a; --q-ink-soft:#5d5749; /* 6.9:1 on bg */
  --q-brand:#bb4430; --q-success:#4f7a6b; --q-warning:#b07714; --q-critical:#9c2f1e;
  /* DISC: fills keep the brand hues; -text variants pass 4.5:1 on surface.
     Re-checked against #fbf8f0 rather than #ffffff: the worst case,
     --q-disc-i-text on surface, moves 5.70:1 -> 5.37:1, still clear of AA. */
  --q-disc-d:#bb4430; --q-disc-d-text:#a63a28;
  --q-disc-i:#d99a2b; --q-disc-i-text:#8a5e0f;
  --q-disc-s:#4f7a6b; --q-disc-s-text:#3f6356;
  --q-disc-c:#3a5a8c; --q-disc-c-text:#32517f;
  /* spacing (4px base) */
  --q-s1:4px; --q-s2:8px; --q-s3:12px; --q-s4:16px; --q-s5:24px; --q-s6:32px; --q-s7:48px;
  /* type scale */
  --q-t-xs:12px; --q-t-sm:14px; --q-t-md:16px; --q-t-lg:20px; --q-t-xl:24px; --q-t-2xl:32px;
  /* The three brand faces every app page already <link>s from Google Fonts.
     Same fallback stacks as before, brand face prepended - without this,
     adopting a q-* class silently swaps Hanken/Spline for system sans. */
  --q-font-display:"Bricolage Grotesque",-apple-system,sans-serif;
  --q-font-body:"Hanken Grotesque",-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;
  --q-font-mono:"Spline Sans Mono","Courier New",ui-monospace,Menlo,monospace;
  --q-radius:0px; --q-radius-soft:3px;
  --q-shadow:3px 3px 0 var(--q-ink);
  --q-target:44px; /* minimum touch target */
}

/* ---- base + accessibility ---- */
.q-scope{font-family:var(--q-font-body);font-size:var(--q-t-md);color:var(--q-ink);line-height:1.5}
/* One focus colour for the whole client area, and it is AMBER. It used to be
   --q-disc-c (blue), which was fine on its own but is not what the shipped
   marketing side does, and blue is not a state colour anywhere else in this
   language. See the note at .q-btn:focus-visible for why ink is not an
   option. Fillable fields are the deliberate exception and keep the 3px ink
   ring - that rule is stated at the very foot of this file so it outranks
   every generic ring here. */
.q-scope :focus-visible{outline:3px solid var(--q-disc-i);outline-offset:2px}
@media (prefers-reduced-motion: reduce){
  .q-scope *,.q-scope *::before,.q-scope *::after{animation-duration:.01ms!important;transition-duration:.01ms!important;scroll-behavior:auto!important}
}

/* ---- buttons ---- */
.q-btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:var(--q-target);
  padding:10px 18px;border:2px solid var(--q-ink);background:var(--q-surface);color:var(--q-ink);
  font:700 var(--q-t-sm)/1.2 var(--q-font-body);cursor:pointer;text-decoration:none;border-radius:var(--q-radius);
  /* Lift machinery - see THE LIFT below. --q-rest is the offset of the
     variant's own rest shadow (0px = none visible, 2px mirrors
     --q-shadow-sm, 3px mirrors --q-shadow). --q-lift is how far the button
     rises off it. --q-btn-bg-hover is the "boldened" background.
     A variant only ever has to restate these three. */
  --q-rest:0px;--q-lift:3px;--q-btn-bg-hover:var(--q-bg-deep);
  box-shadow:var(--q-rest) var(--q-rest) 0 var(--q-ink);
  transition:transform .12s ease,box-shadow .12s ease,background-color .12s ease,color .12s ease,border-color .12s ease}
.q-btn--primary{background:var(--q-brand);color:#fff;box-shadow:var(--q-shadow);
  --q-rest:3px;--q-btn-bg-hover:var(--q-brand-deep)}
.q-btn--quiet{border-color:var(--q-border);font-weight:600}
.q-btn--sm{min-height:36px;padding:6px 12px;font-size:var(--q-t-xs);--q-lift:2px}
.q-btn[disabled]{opacity:.55;cursor:default}

/* ---- THE LIFT ----------------------------------------------------------
   Rod, on the find-a-job buttons: "its lifting only the button, but the
   shaddow box stays, making it even more obvious."

   A box-shadow travels with its element, so translating a button without
   growing the offset slides button and shadow together and the eye reads
   nothing at all. That was the bug here: .q-btn--solid:hover moved -1px
   and left var(--q-shadow) untouched.

   So on hover the offset GROWS by exactly the distance the button rises.
   The shadow's position on screen never changes; only the dark gap it
   reveals gets bigger. On press the button drops 1px back down and the
   offset shrinks 1px to match, so the shadow still holds its ground.

   Variants with no visible shadow keep --q-rest:0px. An outer box-shadow
   with zero offset, blur and spread is clipped away entirely by its own
   border-box, so those buttons look exactly as they always did at rest and
   still get the reveal on hover. Nothing about any rest state moves.

   Disabled never lifts - hence :not([disabled]) rather than a pile of
   [disabled]:hover unwinds. */
.q-btn:hover:not([disabled]){
  transform:translate(calc(-1 * var(--q-lift)),calc(-1 * var(--q-lift)));
  box-shadow:calc(var(--q-rest) + var(--q-lift)) calc(var(--q-rest) + var(--q-lift)) 0 var(--q-ink);
  background:var(--q-btn-bg-hover)}
.q-btn:active:not([disabled]){
  transform:translate(1px,1px);
  box-shadow:max(0px,calc(var(--q-rest) - 1px)) max(0px,calc(var(--q-rest) - 1px)) 0 var(--q-ink);
  background:var(--q-btn-bg-hover)}
@media (prefers-reduced-motion: reduce){
  /* Drop the animation, keep the state - the button still lifts, it just
     arrives there instantly. */
  .q-btn{transition:none}
}

/* ---- inputs ---- */
.q-input,.q-select{width:100%;min-height:var(--q-target);border:1.6px solid var(--q-ink);background:var(--q-surface);
  padding:10px 12px;font:400 var(--q-t-md) var(--q-font-body);color:var(--q-ink);border-radius:var(--q-radius)}
.q-input--error{border-color:var(--q-critical)}
.q-label{display:block;font:700 var(--q-t-sm) var(--q-font-body);margin:var(--q-s4) 0 var(--q-s1)}
.q-help{font-size:var(--q-t-xs);color:var(--q-ink-soft);margin-top:var(--q-s1)}
.q-error{font-size:var(--q-t-sm);color:var(--q-critical);font-weight:600;margin-top:var(--q-s2)}

/* ---- chips & badges ---- */
.q-chip{display:inline-flex;align-items:center;gap:5px;font:600 10px var(--q-font-mono);letter-spacing:.06em;
  text-transform:uppercase;padding:4px 9px;border:1.4px solid var(--q-ink);background:var(--q-surface);border-radius:var(--q-radius-soft)}
.q-chip--d{background:var(--q-disc-d);border-color:var(--q-disc-d);color:#fff}
.q-chip--i{background:var(--q-disc-i);border-color:var(--q-disc-i);color:#211f1a}/* dark text on yellow: 7.6:1 */
.q-chip--s{background:var(--q-disc-s);border-color:var(--q-disc-s);color:#fff}
.q-chip--c{background:var(--q-disc-c);border-color:var(--q-disc-c);color:#fff}
.q-badge--ok{background:var(--q-success);border-color:var(--q-success);color:#fff}
.q-badge--warn{background:var(--q-warning);border-color:var(--q-warning);color:#fff}
.q-badge--critical{background:var(--q-critical);border-color:var(--q-critical);color:#fff}

/* ---- cards, page headers, empty states ---- */
.q-card{border:2px solid var(--q-ink);background:var(--q-surface);padding:var(--q-s4)}
.q-page-header{display:flex;justify-content:space-between;align-items:flex-end;gap:var(--q-s3);flex-wrap:wrap;margin-bottom:var(--q-s5)}
.q-page-header h1{font:800 var(--q-t-2xl)/1.05 var(--q-font-display);margin:0;letter-spacing:-.01em}
.q-empty{border:2px dashed var(--q-border);background:var(--q-surface);padding:var(--q-s6) var(--q-s5);text-align:center}
.q-empty b{display:block;font-size:var(--q-t-lg);margin-bottom:var(--q-s2)}
.q-empty p{color:var(--q-ink-soft);font-size:var(--q-t-sm);max-width:46ch;margin:0 auto var(--q-s4)}

/* ---- tabs ----
   The UNDERLINE strip. Not .q-segtab further down, which is the solid
   button strip the app pages actually ship.

   Rod: "The tabs on the Dashboard outline but don't lift." They had no
   hover, no active and no focus state at all - a selected underline and
   nothing else.

   THEY DO NOT GET THE BUTTON LIFT, and the reason is structural rather
   than taste. A .q-tab is welded to the strip's own 2px baseline by
   margin-bottom:-2px: its underline IS a 2.5px continuation of that rule.
   Translate it -3px and the selected tab's underline tears away from the
   line it is meant to complete, leaving a floating dash 3px above a gap.
   And the lift only reads because a hard shadow holds its ground while the
   element leaves it - a tab has a transparent background and no shadow to
   leave behind, so there would be nothing to reveal.

   So a tab gets the honest equivalent, which is the treatment Rod already
   likes on rows: the surface shades, and the underline thickens from
   nothing to a visible rule. Hovering an unselected tab previews exactly
   what choosing it looks like. Padding widened from 2px to 12px because a
   2px-wide box has nothing to shade; .q-tabs' gap drops from 16px to 8px
   so the space BETWEEN labels stays where it was.

   Focus ring is amber and INSET (outline-offset:-3px): .q-tabs is
   overflow-x:auto, and an outward ring on the first or last tab is clipped
   by that scroll box. */
.q-tabs{display:flex;gap:var(--q-s2);border-bottom:2px solid var(--q-border);margin-bottom:var(--q-s4);overflow-x:auto}
.q-tab{padding:10px 12px;min-height:var(--q-target);display:inline-flex;align-items:center;font:600 var(--q-t-sm) var(--q-font-body);
  color:var(--q-ink-soft);border-bottom:2.5px solid transparent;margin-bottom:-2px;cursor:pointer;white-space:nowrap;background:none;border-top:0;border-left:0;border-right:0;
  transition:background-color .12s ease,color .12s ease,border-color .12s ease}
.q-tab:hover{color:var(--q-ink);background:var(--q-bg-deep);border-bottom-color:var(--q-ink-soft)}
.q-tab:focus-visible{color:var(--q-ink);background:var(--q-bg-deep);
  outline:3px solid var(--q-disc-i);outline-offset:-3px}
/* .q-on / .on are supported alongside .q-tab--on because every tab strip in
   this app toggles a bare class in JS. Stated AFTER :hover on purpose, so a
   selected tab keeps its ink text and brand underline while it is hovered. */
.q-tab--on,.q-tab.q-on,.q-tab.on{color:var(--q-ink);border-bottom-color:var(--q-brand);font-weight:700}
.q-tab--on:hover,.q-tab.q-on:hover,.q-tab.on:hover{border-bottom-color:var(--q-brand-deep)}

/* ---- the responsive table (the mobile dashboard fix) ---- */
.q-table{width:100%;border-collapse:collapse;background:var(--q-surface);font-size:var(--q-t-sm)}
.q-table th{background:var(--q-ink);color:var(--q-bg);font:600 10px var(--q-font-mono);letter-spacing:.1em;
  text-transform:uppercase;padding:8px 10px;text-align:left}
.q-table td{border:1px solid var(--q-border);padding:9px 10px;vertical-align:middle}
.q-table .q-num{text-align:right;font-variant-numeric:tabular-nums}
.q-table th.q-num{text-align:right}
@media (max-width:720px){
  .q-table thead{position:absolute;left:-9999px}
  .q-table,.q-table tbody,.q-table tr,.q-table td{display:block;width:100%}
  .q-table tr{border:2px solid var(--q-ink);margin-bottom:var(--q-s3);background:var(--q-surface)}
  .q-table td{border:0;border-bottom:1px solid var(--q-border);display:flex;justify-content:space-between;gap:var(--q-s3);align-items:baseline}
  .q-table td:last-child{border-bottom:0}
  .q-table td[data-label]::before{content:attr(data-label);font:600 9.5px var(--q-font-mono);letter-spacing:.08em;
    text-transform:uppercase;color:var(--q-ink-soft);flex:none}
  .q-table td.q-rowtitle{font-weight:800;font-size:var(--q-t-md);background:var(--q-bg)}
  .q-table td.q-rowtitle::before{content:none}
  .q-table .q-num{text-align:right}
}

/* ---- progress ---- */
.q-progress{height:10px;border:1.5px solid var(--q-ink);background:var(--q-surface);position:relative}
.q-progress i{position:absolute;inset:0;right:auto;background:var(--q-success);transition:width .3s}

/* ---- toast ---- */
.q-toast{position:fixed;left:50%;bottom:var(--q-s5);transform:translateX(-50%);background:var(--q-ink);color:var(--q-bg);
  padding:12px 18px;font:600 var(--q-t-sm) var(--q-font-body);box-shadow:var(--q-shadow);z-index:9999;max-width:92vw}

/* ---- mobile bottom nav (for the Phase 3 shell; ready now) ---- */
.q-bottomnav{display:none}
@media (max-width:720px){
  .q-bottomnav{display:flex;position:fixed;left:0;right:0;bottom:0;background:var(--q-surface);
    border-top:2px solid var(--q-ink);z-index:999;padding-bottom:env(safe-area-inset-bottom)}
  .q-bottomnav a{flex:1;min-height:var(--q-target);display:flex;flex-direction:column;align-items:center;justify-content:center;
    gap:2px;font:600 10px var(--q-font-body);color:var(--q-ink-soft);text-decoration:none;padding:6px 2px}
  .q-bottomnav a.q-on{color:var(--q-brand);font-weight:800}
  .q-has-bottomnav{padding-bottom:76px}
}

/* ============================================================
   PHASE 3 EXTENSION (Aug 2026)
   Everything below was ADDED so the four app pages can stop
   hand-rolling .btn / .card / table / .tag / .tabs. No rule
   above this banner was restyled; only --q-font-body and
   --q-font-mono were pointed at the brand faces the pages
   already load, because otherwise adopting a q-* class would
   silently change the typeface.

   The language, unchanged: cream paper, near-black ink, SQUARE
   corners, hard offset shadows, 2px solid ink borders, 44px
   minimum targets, Bricolage 800 display, Hanken body, Spline
   Sans Mono uppercase-tracked labels. DISC hues are fixed.

   Shadow scale: 2px small control / 3px control / 6px card.
   ============================================================ */

:root{
  --q-bg-deep:#ebe3d2;              /* the pages' --paper-deep */
  --q-shadow-sm:2px 2px 0 var(--q-ink);
  --q-shadow-lg:6px 6px 0 var(--q-ink);
  --q-wrap:1080px;
  /* Hover fills. Rod: "bolden the background". A filled button goes one
     step deeper into its own hue on hover; an outlined one fills from
     --q-bg to --q-bg-deep. These are each the rest hue at 85% lightness,
     which only ever RAISES contrast against the text sitting on it:
     white on --q-disc-s-deep is 6.2:1 (was 4.9:1), and --q-ink on
     --q-disc-i-deep is 5.7:1 (was 7.6:1), both clear of AA.
     --q-brand-deep serves --q-btn--primary and --q-btn--d, which are the
     same #bb4430 at rest. Used only in hover states - no rest colour in
     this file changes. */
  --q-ink-deep:#12110d;
  /* OPTION C (Rod, 12 Aug 2026). A clickable DARK surface is a warm
     charcoal; its shadow stays true --q-ink and so stays the darkest value
     on screen. Black-on-black merged into one shape and the lift was
     invisible - this separates them by removing the sameness rather than
     adding an outline or greying the shadow. Non-clickable dark ground
     keeps --q-ink: it is the floor, not an object. */
  --q-face:#33302a; --q-face-hover:#43403a;
  --q-brand-deep:#9f3a29;
  --q-disc-i-deep:#b98124;
  --q-disc-s-deep:#43685b;
  --q-disc-c-deep:#314c77;
}

/* ---- page container + layout utilities ---- */
.q-wrap{max-width:var(--q-wrap);margin:0 auto;padding:var(--q-s6) var(--q-s5) 80px;box-sizing:border-box}
.q-row{display:flex;align-items:center;gap:var(--q-s3);flex-wrap:wrap}
.q-row--split{justify-content:space-between}
.q-row--baseline{align-items:baseline}
.q-grid2{display:grid;grid-template-columns:1fr 1fr;gap:var(--q-s4) var(--q-s5);align-items:start}
.q-formbar{display:flex;gap:var(--q-s3);flex-wrap:wrap;align-items:stretch}
.q-formbar>.q-input,.q-formbar>.q-select{flex:1 1 200px;width:auto;min-width:0}
.q-stats{display:flex;gap:var(--q-s4);flex-wrap:wrap;margin:0 0 var(--q-s5)}
.q-linkbox{display:flex;gap:var(--q-s2);align-items:center;margin-top:var(--q-s2)}
.q-linkbox .q-input{font:400 var(--q-t-xs) var(--q-font-mono)}
@media (max-width:900px){.q-grid2{grid-template-columns:1fr}}
@media (max-width:720px){.q-wrap{padding:var(--q-s5) var(--q-s4) 80px}}

/* ---- typography helpers (the pages' .display / .mono / .muted / .note) ---- */
.q-display{font-family:var(--q-font-display);font-weight:800;letter-spacing:-.02em}
.q-mono{font-family:var(--q-font-mono);text-transform:uppercase;letter-spacing:.1em;font-weight:600}
.q-muted{color:var(--q-ink-soft)}
.q-note{padding:var(--q-s3) var(--q-s4);border:2px dashed var(--q-border);background:var(--q-bg);color:var(--q-ink-soft);font-size:var(--q-t-sm)}
/* .q-crumb was the app's one and only "go back" class, and it was 11px
   uppercase mono in muted grey with no border and no ground - the styling
   of a caption, on a control. It is now .q-btn--back (see the buttons
   below); this rule stays only so that a page still carrying the old class
   inherits the new look instead of silently keeping the old one. */
.q-crumb{display:inline-flex;align-items:center;gap:8px;margin-bottom:var(--q-s4);min-height:var(--q-target);
  padding:6px 12px;border:2px solid var(--q-ink);border-radius:var(--q-radius);background:var(--q-surface);
  color:var(--q-ink);text-decoration:none;font:700 var(--q-t-xs)/1.2 var(--q-font-body);
  box-shadow:2px 2px 0 var(--q-ink);transition:transform .12s ease,box-shadow .12s ease}
.q-crumb:hover{color:var(--q-ink);transform:translate(-1px,-1px);box-shadow:3px 3px 0 var(--q-ink)}
.q-linkbtn{background:none;border:0;padding:0;cursor:pointer;color:var(--q-disc-c-text);
  font:600 13px var(--q-font-body);text-decoration:underline}
.q-saved{display:none;color:var(--q-disc-s-text);font-weight:700;font-size:13px;margin-left:var(--q-s2)}
.q-saved.q-on,.q-saved.on{display:inline}

/* Loading. One string, one mark, reduced-motion safe. */
.q-loading{display:inline-flex;align-items:center;gap:var(--q-s2);color:var(--q-ink-soft);font-size:var(--q-t-sm)}
.q-spin{width:14px;height:14px;border:2px solid var(--q-border);border-top-color:var(--q-ink);
  display:inline-block;flex:none;animation:q-spin .7s linear infinite}
@keyframes q-spin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion: reduce){.q-spin{animation:none;border-top-color:var(--q-border)}}

/* ---- section headings + card headings ---- */
.q-section{display:flex;align-items:baseline;gap:var(--q-s3);flex-wrap:wrap;
  margin:var(--q-s6) 0 var(--q-s3);border-bottom:2px solid var(--q-ink);padding-bottom:var(--q-s2)}
.q-section-title{font:800 var(--q-t-lg)/1.1 var(--q-font-display);letter-spacing:-.02em;margin:0}
.q-section-meta{font:600 11px var(--q-font-mono);text-transform:uppercase;letter-spacing:.1em;color:var(--q-ink-soft)}
.q-card-title{font:800 var(--q-t-lg)/1.15 var(--q-font-display);letter-spacing:-.02em;margin:0 0 var(--q-s1)}
.q-card-eyebrow{font:600 11px var(--q-font-mono);text-transform:uppercase;letter-spacing:.1em;
  color:var(--q-ink-soft);margin:0 0 var(--q-s1)}

/* ---- buttons: the variants the pages encode with inline style ---- */
/* The filled ink button that every page calls plain ".btn". */
.q-btn--solid{background:var(--q-face);color:var(--q-bg);border-color:var(--q-face);box-shadow:var(--q-shadow);
  --q-rest:3px;--q-btn-bg-hover:var(--q-face-hover)}
/* Small shadowed controls step down to the 2px shadow - and, via
   .q-btn--sm's --q-lift:2px, to a 2px lift, so the shadow still stays put
   and the reveal stays in proportion to the smaller control. */
.q-btn--solid.q-btn--sm,.q-btn--primary.q-btn--sm{box-shadow:var(--q-shadow-sm);--q-rest:2px}
/* Destructive: outlined in critical red, never filled, never shadowed.
   Replaces every inline color:var(--d) / border-color:var(--d) button.
   Its hover fill was already the "bolden" - it is now stated as the token
   so THE LIFT's one background rule cannot outrank it. */
.q-btn--danger{background:transparent;color:var(--q-critical);border-color:var(--q-critical);font-weight:700;
  --q-btn-bg-hover:var(--q-critical)}
.q-btn--danger:hover:not([disabled]){color:#fff}
/* Low-emphasis: soft border, soft ink, no shadow (dismiss / skip / not now). */
.q-btn--muted{background:transparent;color:var(--q-ink-soft);border-color:var(--q-border);font-weight:600}
.q-btn--muted:hover:not([disabled]){color:var(--q-ink);border-color:var(--q-ink)}
/* Ghost: outlined ink on whatever it sits on, no shadow. */
.q-btn--ghost{background:transparent}
/* ---- Back: the way out of a page, and it looks like one --------------
   Rod, 13 Aug 2026: "The back button infastructure accross the site is
   terrible. Hardly noticeable, can we make it a proper button like
   everything else?"

   He was right, and the cause was that the app offered exactly one class
   for it - .q-crumb, a caption - so every page that wanted something
   visible invented its own. Seven treatments of one idea across the site,
   none of them obviously pressable.

   This is simply a q-btn: the same 2px border, hard shadow, lift and
   44px target as every other control, with a resting shadow so it reads
   as raised rather than printed on. The arrow is drawn HERE rather than
   typed into each page, so it cannot drift, cannot be forgotten, and is
   not read out by a screen reader as part of the label.

   Put it on an <a>, never a <button> calling history.back(). Going back
   is navigation: people middle-click and cmd-click it and expect a real
   destination, and a scripted history pop lands somewhere different
   depending on how you arrived - which is the unpredictability that made
   these untrustworthy in the first place. */
.q-btn--back{--q-rest:2px}
.q-btn--back::before{content:"\2190";font-size:1.15em;line-height:1}
/* DISC-hue destination buttons (Guide=I, Align=S, Link/Pool=C, Delete=D).
   I keeps ink text - cream on #d99a2b fails contrast, which is what the
   pages do today by inheriting .btn's color. */
/* 2px rest shadow, so a 2px lift at every size - the shadow must still
   land exactly where it sat. */
.q-btn--d{background:var(--q-disc-d);border-color:var(--q-disc-d);color:#fff;box-shadow:var(--q-shadow-sm);
  --q-rest:2px;--q-lift:2px;--q-btn-bg-hover:var(--q-brand-deep)}
.q-btn--i{background:var(--q-disc-i);border-color:var(--q-disc-i);color:var(--q-ink);box-shadow:var(--q-shadow-sm);
  --q-rest:2px;--q-lift:2px;--q-btn-bg-hover:var(--q-disc-i-deep)}
.q-btn--s{background:var(--q-disc-s);border-color:var(--q-disc-s);color:#fff;box-shadow:var(--q-shadow-sm);
  --q-rest:2px;--q-lift:2px;--q-btn-bg-hover:var(--q-disc-s-deep)}
.q-btn--c{background:var(--q-disc-c);border-color:var(--q-disc-c);color:#fff;box-shadow:var(--q-shadow-sm);
  --q-rest:2px;--q-lift:2px;--q-btn-bg-hover:var(--q-disc-c-deep)}
/* A filled button's border IS its fill, so it deepens with it - otherwise
   the old lighter hue survives as a ring around the boldened face. */
.q-btn--solid:hover:not([disabled]),.q-btn--primary:hover:not([disabled]),
.q-btn--d:hover:not([disabled]),.q-btn--i:hover:not([disabled]),
.q-btn--s:hover:not([disabled]),.q-btn--c:hover:not([disabled]){border-color:var(--q-btn-bg-hover)}
/* Outlined DISC-hue, for the secondary action sitting beside a filled one
   (Copy link, Resend login link). There is deliberately no --line-d:
   an outlined red button is always .q-btn--danger, so there is exactly
   one way to say "destructive". */
.q-btn--line-i{background:transparent;border-color:var(--q-disc-i);color:var(--q-disc-i-text)}
.q-btn--line-s{background:transparent;border-color:var(--q-disc-s);color:var(--q-disc-s-text)}
.q-btn--line-c{background:transparent;border-color:var(--q-disc-c);color:var(--q-disc-c-text)}
/* Focus is not inherited from .q-scope, so state it on the component.
   THE RING IS AMBER, NOT INK AND NOT BLUE, and that is the whole point.
   An outline paints AFTER the element's own box-shadow, so an ink ring at
   a positive offset lands inside the hard ink shadow these controls cast
   and disappears along their right and bottom edges - half a ring, which
   reads as a rendering fault rather than as focus. Amber is a brand colour
   and reads against the paper, against the ink shadow and against all four
   DISC fills. Same ring the marketing side already ships on .btn and
   .tlink, so the two halves of the site now answer the keyboard alike. */
.q-btn:focus-visible,.q-linkbtn:focus-visible,.q-segtab:focus-visible,.q-stat:focus-visible{outline:3px solid var(--q-disc-i);outline-offset:3px}

/* ---- form controls ---- */
.q-textarea{width:100%;min-height:120px;border:1.6px solid var(--q-ink);background:var(--q-surface);
  padding:12px 14px;font:400 var(--q-t-md)/1.5 var(--q-font-body);color:var(--q-ink);
  border-radius:var(--q-radius);resize:vertical;box-sizing:border-box}
.q-textarea--mono{font:400 13px/1.5 var(--q-font-mono);text-transform:none;letter-spacing:0}
.q-input--inline{width:auto;min-width:0;flex:1 1 180px}
/* Standard rule, stated again site-wide at the foot of this file: a
   fillable field that has focus is outlined in ink, so a person always
   knows which box they are in. :focus, not :focus-visible - Rod's rule is
   about clicking into a field with a mouse. The border underneath is left
   alone; the outline sits outside it. */
.q-input:focus,.q-select:focus,.q-textarea:focus{outline:3px solid var(--q-ink);outline-offset:2px}
.q-input[disabled],.q-select[disabled],.q-textarea[disabled]{background:var(--q-bg-deep);color:var(--q-ink-soft);cursor:default}
/* The uppercase tracked field label the brand actually uses. */
.q-label--mono{font:600 11px var(--q-font-mono);text-transform:uppercase;letter-spacing:.1em;color:var(--q-ink-soft)}

/* ---- cards ----
   Two objects, deliberately: .q-panel is the flagship card every page
   calls ".card" (cream, 2px ink, 6px hard shadow). .q-card stays the
   plain bordered box; the modifiers below dress it up when needed. */
.q-panel{border:2px solid var(--q-ink);background:var(--q-bg);box-shadow:var(--q-shadow-lg);
  padding:var(--q-s5);margin:0 0 var(--q-s5);border-radius:var(--q-radius)}
.q-panel--flat{box-shadow:none;padding:var(--q-s4) 18px;margin-bottom:var(--q-s3)}
.q-panel--danger,.q-card--danger{border-color:var(--q-critical);box-shadow:6px 6px 0 var(--q-critical)}
.q-panel--danger .q-card-title,.q-card--danger .q-card-title{color:var(--q-critical)}
.q-card--paper{background:var(--q-bg)}
.q-card--raised{box-shadow:var(--q-shadow-lg)}
.q-card--lg{padding:var(--q-s5)}
.q-card+.q-card{margin-top:var(--q-s5)}

/* ---- stat tiles (Overview) ---- */
.q-stat{flex:1 1 150px;min-width:150px;border:2px solid var(--q-ink);background:var(--q-bg);
  box-shadow:var(--q-shadow-lg);padding:18px 20px;cursor:pointer;text-align:left;
  font:inherit;color:inherit;min-height:var(--q-target);display:block;
  transition:transform .12s ease,box-shadow .12s ease,background-color .12s ease}
/* A stat tile is a button, so it lifts like one. 6px rest shadow -> 9px on
   hover for a 3px rise, which still clears the 16px gap between tiles. */
.q-stat:hover{transform:translate(-3px,-3px);box-shadow:9px 9px 0 var(--q-ink);background:var(--q-bg-deep)}
.q-stat:active{transform:translate(1px,1px);box-shadow:5px 5px 0 var(--q-ink);background:var(--q-bg-deep)}
.q-stat-n{display:block;font:800 38px/1 var(--q-font-display);letter-spacing:-.02em}
.q-stat-label{display:block;font:600 10px var(--q-font-mono);text-transform:uppercase;
  letter-spacing:.1em;color:var(--q-ink-soft);margin-top:6px}

/* ---- segmented tab strip (the in-page .tabs / #qsubtabs / .seg) ----
   NOT the same thing as .q-tabs above: .q-tabs is the underline pattern
   the top nav uses. This is the solid-button strip every app page ships.
   `.on` is supported alongside `.q-on` because dashboard.html, hiring.html
   and quadrant-org.js all toggle the bare class in JS.

   ---- THE SUB-HEADER ROW CARRIES THE BUTTON STANDARD (Aug 2026) ----
   Rod: "You didn't apply the button formatting to the sub header row
   buttons accross all the pages inside, People, Org Chard, Playbooks,
   Create a Role, Open Roles, Talent pool and Archive are all old
   formating."

   Every one of those seven is a .q-segtab, and every one of them is
   defined HERE, not in the pages - dashboard.html and hiring.html emit
   `class="q-segtab"` in template strings and quadrant-org.js builds the
   People / Org chart / Playbooks strip the same way. So this block is the
   only place the seven change, and no page edit is needed for them.

   They were flat: a border-colour swap on hover and nothing else. They now
   carry THE LIFT, with one deliberate restraint.

   REST STATE IS UNTOUCHED, and that is on purpose. --q-segrest stays 0px,
   so no segtab gains a resting shadow - which above all means the SELECTED
   one, an ink-filled box, does not gain an ink shadow underneath it. That
   is the black-box-on-black-shadow question Rod is still choosing between,
   and it is not this batch's to answer. Flip --q-segrest to 3px on this
   one rule if he decides he wants it; every state below derives from it.

   The lift still works with a zero rest shadow, and that is the mechanism
   .q-btn's default variant already uses: an outer box-shadow with zero
   offset, blur and spread is clipped away entirely by its own border-box,
   so at rest there is nothing to see. On hover the button rises 3px and
   the offset grows to 3px, which puts the shadow's screen position exactly
   where the button was sitting. On press it drops 1px past rest and the
   shadow closes again. */
.q-segtabs{display:flex;gap:var(--q-s2);flex-wrap:wrap;margin:var(--q-s2) 0 var(--q-s5)}
.q-segtab{display:inline-flex;align-items:center;justify-content:center;min-height:var(--q-target);
  padding:10px 20px;border:2px solid var(--q-border);background:var(--q-bg);color:var(--q-ink-soft);
  font:700 var(--q-t-sm) var(--q-font-body);cursor:pointer;text-decoration:none;
  border-radius:var(--q-radius);box-sizing:border-box;white-space:nowrap;
  --q-segrest:0px;--q-seglift:3px;
  box-shadow:var(--q-segrest) var(--q-segrest) 0 var(--q-ink);
  transition:transform .12s ease,box-shadow .12s ease,background-color .12s ease,border-color .12s ease,color .12s ease}
/* Unselected: the fill boldens from paper to paper-deep, the soft border
   goes to ink, and the shadow appears under a button that has moved off it. */
.q-segtab:hover,.q-segtab:focus-visible{color:var(--q-ink);border-color:var(--q-ink);background:var(--q-bg-deep);
  transform:translate(calc(-1 * var(--q-seglift)),calc(-1 * var(--q-seglift)));
  box-shadow:calc(var(--q-segrest) + var(--q-seglift)) calc(var(--q-segrest) + var(--q-seglift)) 0 var(--q-ink)}
.q-segtab:active{transform:translate(1px,1px);background:var(--q-bg-deep);
  box-shadow:max(0px,calc(var(--q-segrest) - 1px)) max(0px,calc(var(--q-segrest) - 1px)) 0 var(--q-ink)}
/* Selected, stated after :hover so it still reads as selected while hovered:
   ink fill, ink border, cream text, exactly as before. Its hover only
   deepens the fill - the ink surface's resting look does not move. */
.q-segtab.q-on,.q-segtab.on{border-color:var(--q-face);background:var(--q-face);color:var(--q-bg)}
.q-segtab.q-on:hover,.q-segtab.on:hover,
.q-segtab.q-on:focus-visible,.q-segtab.on:focus-visible,
.q-segtab.q-on:active,.q-segtab.on:active{background:var(--q-face-hover);border-color:var(--q-face-hover);color:var(--q-bg)}
.q-segtab--d{border-color:var(--q-disc-d);color:var(--q-disc-d-text)}
.q-segtab--i{border-color:var(--q-disc-i);color:var(--q-disc-i-text)}
.q-segtab--s{border-color:var(--q-disc-s);color:var(--q-disc-s-text)}
.q-segtab--c{border-color:var(--q-disc-c);color:var(--q-disc-c-text)}

/* ---- vertical section nav (settings .snav) ---- */
.q-sidenav{display:flex;flex-direction:column;gap:2px}
.q-sidenav button{all:unset;box-sizing:border-box;cursor:pointer;padding:12px 14px;
  border:2px solid transparent;color:var(--q-ink-soft);font:600 var(--q-t-sm) var(--q-font-body);
  min-height:var(--q-target);display:flex;align-items:center}
.q-sidenav button:hover{color:var(--q-ink)}
.q-sidenav button.q-on,.q-sidenav button.on{border-color:var(--q-ink);background:var(--q-bg-deep);
  color:var(--q-ink);box-shadow:3px 3px 0 var(--q-ink)}
@media (max-width:760px){.q-sidenav{flex-direction:row;flex-wrap:wrap;overflow-x:auto}}

/* ---- chips: mono uppercase micro-labels, DISC letters, statuses ---- */
.q-chip--muted{background:var(--q-ink-soft);border-color:var(--q-ink-soft);color:#fff}
/* Outlined counterparts, for status that should not shout. */
.q-chip--line-d{background:transparent;border-color:var(--q-disc-d);color:var(--q-disc-d-text)}
.q-chip--line-i{background:transparent;border-color:var(--q-disc-i);color:var(--q-disc-i-text)}
.q-chip--line-s{background:transparent;border-color:var(--q-disc-s);color:var(--q-disc-s-text)}
.q-chip--line-c{background:transparent;border-color:var(--q-disc-c);color:var(--q-disc-c-text)}

/* ---- tags: body font, sentence case, for content-bearing labels ----
   (.q-chip shouts in uppercase mono; a company name must not.) */
.q-tag{display:inline-block;border:2px solid var(--q-ink);background:var(--q-bg-deep);
  padding:3px 9px;font:600 var(--q-t-xs) var(--q-font-body);color:var(--q-ink);
  border-radius:var(--q-radius);margin:2px 3px 2px 0}
.q-tag--d{border-color:var(--q-disc-d);color:var(--q-disc-d-text)}
.q-tag--i{border-color:var(--q-disc-i);color:var(--q-disc-i-text)}
.q-tag--s{border-color:var(--q-disc-s);color:var(--q-disc-s-text)}
.q-tag--c{border-color:var(--q-disc-c);color:var(--q-disc-c-text)}
.q-tag--muted{border-color:var(--q-border);color:var(--q-ink-soft);background:var(--q-bg)}

/* ---- callouts (hiring's .q question block, .flag, .miss, .warn) ---- */
.q-callout{margin:0 0 var(--q-s3);padding:var(--q-s3) var(--q-s4);background:var(--q-bg-deep);
  border-left:4px solid var(--q-ink);font-size:var(--q-t-sm)}
.q-callout b{display:block;margin-bottom:var(--q-s1)}
.q-callout .q-listen{font-size:12.5px;color:var(--q-ink-soft);display:block}
.q-callout--d{border-left-color:var(--q-disc-d)}
.q-callout--i{border-left-color:var(--q-disc-i)}
.q-callout--s{border-left-color:var(--q-disc-s)}
.q-callout--c{border-left-color:var(--q-disc-c)}

/* ---- labelled meter (hiring .hmeter/.track/.fill; use .q-progress inside) ---- */
.q-meter{margin:7px 0}
.q-meter-top{display:flex;justify-content:space-between;align-items:baseline;gap:var(--q-s2);font-size:var(--q-t-xs)}

/* ---- table additions ---- */
.q-table tr.q-click,.q-table tr.click{cursor:pointer}
.q-table tr.q-click:hover,.q-table tr.click:hover{background:var(--q-bg-deep)}
@media (max-width:720px){
  /* Mirrors the collapse dashboard.html and hiring.html already ship in
     their own #app blocks, so a page can drop that block and lose nothing:
     first cell reads as the row title, empty cells disappear. */
  .q-table td:first-child{font-weight:800;font-size:var(--q-t-md);background:var(--q-bg)}
  .q-table td:first-child::before{content:none}
  .q-table td:empty{display:none}
}

/* ---- DISC ---- */
/* Fills keep the brand hues exactly; text uses the contrast-checked variants. */
.q-fill-d{background:var(--q-disc-d);color:#fff}
.q-fill-i{background:var(--q-disc-i);color:var(--q-ink)}
.q-fill-s{background:var(--q-disc-s);color:#fff}
.q-fill-c{background:var(--q-disc-c);color:#fff}
.q-ink-d{color:var(--q-disc-d-text)}
.q-ink-i{color:var(--q-disc-i-text)}
.q-ink-s{color:var(--q-disc-s-text)}
.q-ink-c{color:var(--q-disc-c-text)}
.q-disc{font:800 15px var(--q-font-display);letter-spacing:.02em}
/* The brandmark used as data: 2x2 quadrant with the dominant letter lit. */
.q-quad{display:grid;grid-template-columns:var(--q-target) var(--q-target);
  grid-template-rows:var(--q-target) var(--q-target);gap:var(--q-s1);flex:none}
.q-quad i{display:block;opacity:.25;font-style:normal}
.q-quad i.q-hot,.q-quad i.hot{opacity:1;outline:3px solid var(--q-ink);outline-offset:2px}

/* ---- disclosure + clickable rows of text ----
   Rod: "I think an outline instead of a highlight is better, make all
   those kinds of lines of text that are clickable, outlined."

   Outline only, on hover and on keyboard focus. No background change, so
   the row keeps its weight on the page and simply declares that it opens.
   .q-clickrow is the utility for any client-side collapsible row that is
   not a <summary>. */
.q-details>summary{cursor:pointer;font:700 13px var(--q-font-body);min-height:var(--q-target);
  display:flex;align-items:center;gap:var(--q-s2)}
.q-clickrow{cursor:pointer}
.q-details>summary:hover,.q-details>summary:focus-visible,
.q-clickrow:hover,.q-clickrow:focus-visible{outline:2px solid var(--q-ink);outline-offset:2px}

/* ---- .q-tlink: the amber text-link underline, client side ----
   Rod: "Apply the underline yellow effect in the client dashboard area as
   well, especially to My Team page names."

   Same object styles/quadrant.css ships as .tlink, restated on the --q-*
   tokens so it works inside the app, where --i / --d / --ink are not
   necessarily declared. Deliberately NOT a bare-<a> rule the way the
   marketing sheet does it: the marketing sheet can lean on
   `main p > a:not([class])` because every button there carries a class,
   but the app renders links from template strings all over the place and
   an automatic rule would underline half the nav. A name asks for this
   by name.

   Hover DEEPENS the rule to brand red rather than thickening it - growing
   the border by a pixel reflows the line box and shifts every word after
   the link. Ring is amber, offset outward, for the reason given at
   .q-btn:focus-visible.

   NOT for buttons, tabs or the nav: those already have the lift and the
   ring, and an underline under a lifting box is noise. */
.q-tlink{color:var(--q-ink);text-decoration:none;font-weight:800;
  border-bottom:2px solid var(--q-disc-i);padding-bottom:2px;
  transition:border-color .08s,color .08s}
.q-tlink:hover{border-bottom-color:var(--q-brand)}
.q-tlink:focus-visible{outline:3px solid var(--q-disc-i);outline-offset:3px;border-bottom-color:var(--q-brand)}
/* On the ink grounds the ink text colour would vanish; the amber rule still
   reads against the dark, so only the type colour changes. */
.q-toast .q-tlink,.q-tlink.q-on-ink{color:var(--q-bg)}

/* ---- .q-rowclick: the shaded clickable row ----
   Rod, on the talent pool: "each row is shaded as you hover over it.
   That's a nice effect when the row is clickable. It's obvious which row
   you're on."

   This is the SECOND of two clickable-row treatments and they are not
   interchangeable. .q-clickrow above is a line of TEXT that opens
   something - Rod asked for an outline there, "an outline instead of a
   highlight", because a highlight behind a bare line of prose reads as a
   selection. .q-rowclick is a whole table row: it has a box, so the box
   shades.

   Keyboard gets the same shading via :focus-within, which is what fires
   when the row's own link or button takes focus - a <tr> is not focusable
   itself, so :focus alone would never match on the People table. The
   amber marker is painted on the row's FIRST CELL rather than as a
   box-shadow on the row: in a border-collapse table a box-shadow on <tr>
   is unreliable across browsers, and an outline on <tr> is drawn outside
   the collapsed borders and clips against the table edge. Hence Rod's
   "no outline" here, satisfied with an inset rule instead. */
.q-rowclick{cursor:pointer;transition:background-color .12s ease}
.q-rowclick:hover,.q-rowclick:focus-within{background:var(--q-bg-deep)}
.q-rowclick:focus-visible{background:var(--q-bg-deep);outline:none}
.q-rowclick:focus-within>:first-child,.q-rowclick:focus-visible>:first-child{
  box-shadow:inset 3px 0 0 var(--q-disc-i)}
/* Nothing is needed to combine the two. A .q-tlink name inside a .q-rowclick
   keeps its amber rule at all times - Rod asked for the underline ON the My
   Team names, not for one that only appears on hover - and .q-tlink:hover
   still deepens that rule to brand red when the pointer is on the name
   itself rather than merely somewhere in the row. */

/* ============================================================
   PHASE 4 EXTENSION (Aug 2026)
   The in-page replacement for alert / confirm / prompt, driven
   by brand/quadrant-dialog.js. Additive only: no rule above
   this banner was changed, and the one existing .q-toast rule
   is left alone - the stacked variant is scoped inside
   .q-toast-wrap so nothing that used the old rule can move.

   Only settings.html carries .q-scope, so every object below
   states its own font and colour instead of inheriting them.
   Language unchanged: cream paper, near-black ink, square
   corners, hard offset shadows, 44px targets.
   ============================================================ */

/* ---- toasts ---- */
.q-toast-wrap{position:fixed;left:50%;bottom:var(--q-s5);transform:translateX(-50%);z-index:10010;
  display:flex;flex-direction:column;gap:var(--q-s2);align-items:stretch;
  width:min(560px,92vw);pointer-events:none;font-family:var(--q-font-body)}
.q-toast-wrap .q-toast{position:static;left:auto;bottom:auto;transform:none;max-width:none;
  display:flex;align-items:flex-start;gap:var(--q-s3);pointer-events:auto;
  background:var(--q-ink);color:var(--q-bg);border:2px solid var(--q-ink);
  padding:12px 12px 12px 16px;font:600 var(--q-t-sm)/1.45 var(--q-font-body);box-shadow:var(--q-shadow)}
.q-toast-wrap .q-toast--ok{background:var(--q-success);border-color:var(--q-success);color:#fff}
.q-toast-wrap .q-toast--err{background:var(--q-critical);border-color:var(--q-critical);color:#fff}
.q-toast-msg{flex:1;min-width:0}
.q-toast-x{flex:none;min-width:32px;min-height:32px;background:none;border:0;cursor:pointer;
  color:inherit;font:400 20px/1 var(--q-font-body);padding:0;opacity:.75}
.q-toast-x:hover{opacity:1}
.q-toast-x:focus-visible{outline:2px solid var(--q-bg);outline-offset:1px}
@media (max-width:720px){.q-toast-wrap{bottom:var(--q-s3);width:94vw}}

/* ---- the modal shell ---- */
.q-modal{position:fixed;inset:0;z-index:10000;background:rgba(20,18,14,.55);
  display:flex;align-items:flex-start;justify-content:center;overflow:auto;
  padding:8vh 16px 40px;font-family:var(--q-font-body);color:var(--q-ink);font-size:var(--q-t-md);line-height:1.5}
.q-modal-panel{width:100%;max-width:520px;background:var(--q-bg);border:2px solid var(--q-ink);
  box-shadow:var(--q-shadow-lg);border-radius:var(--q-radius);padding:var(--q-s5)}
.q-modal-panel:focus{outline:none}
.q-modal-panel .q-card-title{margin:0}
.q-modal-body{margin:var(--q-s3) 0 0;font-size:var(--q-t-sm);color:var(--q-ink);line-height:1.55}
.q-modal-body p{margin:0 0 var(--q-s2)}
.q-modal-body p:last-child{margin-bottom:0}
.q-modal-field{margin-top:var(--q-s4)}
.q-modal-field .q-label{margin-top:0}
.q-modal-preview{font-weight:600;color:var(--q-ink)}
.q-modal-actions{display:flex;gap:var(--q-s3);flex-wrap:wrap;justify-content:flex-end;margin-top:var(--q-s5)}
/* Amber, and it must be stated here as well as on .q-btn: this rule is
   (0,2,0) and sits LOWER in the file than .q-btn:focus-visible, so whatever
   colour it carries wins for every button inside a dialog. */
.q-modal :focus-visible{outline:3px solid var(--q-disc-i);outline-offset:2px}
@media (max-width:720px){
  .q-modal{padding:4vh 12px 32px}
  .q-modal-panel{padding:var(--q-s4)}
  .q-modal-actions{justify-content:stretch}
  .q-modal-actions .q-btn{flex:1 1 140px}
}
@media (prefers-reduced-motion: reduce){
  .q-modal,.q-modal-panel,.q-toast{animation:none!important;transition:none!important}
}

/* ---- the stacked choice buttons (remove a member, role filled) ---- */
.q-modal-choices{display:flex;flex-direction:column;gap:var(--q-s3);margin-top:var(--q-s4)}
.q-choice{display:block;width:100%;text-align:left;cursor:pointer;
  border:2px solid var(--q-ink);background:var(--q-surface);color:var(--q-ink);
  padding:12px 16px;min-height:var(--q-target);border-radius:var(--q-radius);font:inherit;
  box-shadow:var(--q-shadow-sm);
  transition:transform .12s ease,box-shadow .12s ease,background-color .12s ease}
/* Same mechanism as .q-btn: 2px rest shadow, 2px lift, offset grows to 4px
   so the shadow does not move. It had the same static-feeling -1px hover. */
.q-choice:hover{transform:translate(-2px,-2px);box-shadow:4px 4px 0 var(--q-ink);background:var(--q-bg-deep)}
.q-choice:active{transform:translate(1px,1px);box-shadow:1px 1px 0 var(--q-ink);background:var(--q-bg-deep)}
.q-choice-label{display:block;font:700 var(--q-t-sm) var(--q-font-body)}
.q-choice-help{display:block;margin-top:3px;font:400 var(--q-t-xs)/1.45 var(--q-font-body);color:var(--q-ink-soft)}
.q-choice--danger{border-color:var(--q-critical);box-shadow:2px 2px 0 var(--q-critical)}
.q-choice--danger .q-choice-label{color:var(--q-critical)}
.q-choice--danger:hover{box-shadow:4px 4px 0 var(--q-critical)}
.q-choice--danger:active{box-shadow:1px 1px 0 var(--q-critical)}

/* ---- the inline form, rendered where the action lives ---- */
.q-inline-form{display:block;width:100%;margin:var(--q-s2) 0;padding:var(--q-s3) var(--q-s4);
  border:2px solid var(--q-ink);background:var(--q-bg);border-radius:var(--q-radius);
  font-family:var(--q-font-body);color:var(--q-ink);font-size:var(--q-t-sm);box-shadow:var(--q-shadow-sm)}
.q-inline-title{font:700 var(--q-t-sm) var(--q-font-body);margin-bottom:var(--q-s1)}
.q-inline-form .q-label{margin-top:0}
.q-inline-form .q-input,.q-inline-form .q-textarea{max-width:420px}
.q-inline-preview{font-weight:600;color:var(--q-ink)}
.q-inline-actions{display:flex;gap:var(--q-s2);flex-wrap:wrap;margin-top:var(--q-s3)}
.q-inline-form :focus-visible{outline:3px solid var(--q-disc-i);outline-offset:2px}

/* ---- inline copy row (an email that did not send, a link to hand over) ---- */
.q-copyrow{display:block;width:100%;margin:var(--q-s2) 0;font-family:var(--q-font-body);
  font-size:var(--q-t-sm);color:var(--q-ink)}
.q-copyrow-note{margin:0 0 var(--q-s1);font-size:var(--q-t-xs);color:var(--q-ink-soft)}
.q-copyrow .q-linkbox{flex-wrap:wrap}
.q-copyrow .q-input{flex:1 1 240px;min-width:0}

/* ---- inline field error ---- */
.q-field-error{display:block}

/* ============================================================
   SITE-WIDE STANDARD: FOCUS ON FILLABLE FIELDS (Aug 2026)
   Rod: "Do the same on every fillable field, if someone clicks a fillable
   field on any page, that box it outlined so a user always knows where
   they are and what they are looking at. Make that a standard rule."

   Deliberately :focus and not :focus-visible - the rule exists for a
   person clicking into a box with a mouse, which :focus-visible would
   skip. Outlines take no space in layout and no existing border is
   removed; the ink ring sits outside whatever border the field already
   had.

   Stated here, at the foot of the file, on purpose: the ink ring has to
   outrank .q-modal :focus-visible and .q-inline-form :focus-visible, which
   would otherwise paint a field inside a dialog the generic blue. The bare
   input/textarea/select selectors are so a page that never adopted the
   q-* field classes still gets the standard inside any panel or card.
   ============================================================ */
.q-input:focus,.q-select:focus,.q-textarea:focus,
.q-panel input:focus,.q-panel textarea:focus,.q-panel select:focus,.q-panel [contenteditable]:focus,
.q-card input:focus,.q-card textarea:focus,.q-card select:focus,.q-card [contenteditable]:focus,
.q-modal input:focus,.q-modal textarea:focus,.q-modal select:focus,.q-modal [contenteditable]:focus,
.q-inline-form input:focus,.q-inline-form textarea:focus,.q-inline-form select:focus,
.q-scope input:focus,.q-scope textarea:focus,.q-scope select:focus,.q-scope [contenteditable]:focus{
  outline:3px solid var(--q-ink);outline-offset:2px}

@media (prefers-reduced-motion: reduce){
  /* Lose the travel, keep every state. Someone who asks for less motion
     still gets the lift, the bigger shadow, the shading and the deeper
     fill - they just arrive there instantly. Removing the STATE as well
     would take the affordance away from the people most likely to need it. */
  .q-choice,.q-stat,.q-segtab,.q-tab,.q-tlink,.q-rowclick{transition:none}
}
