/* ==========================================================================
   amida.css — the shared design system. Every page loads this AFTER
   amida-tokens.css, which holds the brand (see docs/frontend/brand/README.md).

   THE RULE: this file defines no colour of its own. Every value below maps a
   semantic name the components use (--paper, --ink, --accent) onto a brand
   token (--amida-cream, --amida-walnut, --amida-pomegranate). Two palettes
   drift; one palette with an alias layer does not. If you need a new colour,
   add it to the brand file and alias it here.

   Mobile-first: the base rules ARE the phone layout; media queries only widen.
   ========================================================================== */

:root {
  /* --- semantic aliases onto the brand ---------------------------------- */
  --paper:      var(--amida-cream);
  --card:       var(--amida-surface);
  --ink:        var(--amida-walnut);
  --ink-soft:   var(--amida-ink-soft);
  --ink-faint:  var(--amida-ink-faint);
  --line:       var(--amida-hairline);
  --accent:     var(--amida-pomegranate);
  --accent-ink: var(--amida-pomegranate);
  --accent-wash: var(--amida-shell);
  --good:       oklch(0.52 0.09 155);
  --warn:       oklch(0.65 0.12 75);

  /* --- type ------------------------------------------------------------- */
  --font: var(--amida-font-ui);
  --font-display: var(--amida-font-display);

  /* --- space + shape ---------------------------------------------------- */
  --gap: 16px;
  --radius: var(--amida-radius-card);
  --radius-pill: var(--amida-radius-chip);
  --shadow: 0 1px 2px oklch(0.25 0.03 40 / .05), 0 8px 24px oklch(0.25 0.03 40 / .07);
  --tap: 44px;           /* minimum touch target — never go below this */
  --max: 620px;          /* the app is a column, even on a desktop */
}

/* The reverse palette — walnut ground, cream ink, rose accent. The brand's own
   second lockup, not an inversion; the handoff specifies rose (not pomegranate)
   on dark because pomegranate on walnut fails AA.
   
   NOT wired to prefers-color-scheme. Cream is "app background" in the brand,
   and a member on a dark-mode phone was getting the reverse lockup as their
   default, which is not what the brand says the product looks like. Opt in
   with <html data-theme="dark"> when there's a setting for it. */
:root[data-theme="dark"] {
    --paper:      var(--amida-walnut);
    --card:       oklch(0.30 0.03 40);
    --ink:        var(--amida-cream);
    --ink-soft:   oklch(0.78 0.03 60);
    --ink-faint:  oklch(0.60 0.03 55);
    --line:       oklch(0.36 0.03 45);
    --accent:     var(--amida-rose);
    --accent-ink: var(--amida-rose);
    --accent-wash: oklch(0.34 0.05 35);
    --shadow: 0 1px 2px oklch(0 0 0 / .3), 0 8px 24px oklch(0 0 0 / .35);
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  font: 16px/1.55 var(--font);
  color: var(--ink);
  background: var(--paper);
  /* iOS safe areas — this is installed to a home screen, so it runs edge to edge */
  padding: env(safe-area-inset-top) env(safe-area-inset-right)
           env(safe-area-inset-bottom) env(safe-area-inset-left);
}

.wrap { max-width: var(--max); margin: 0 auto; padding: 0 var(--gap) 96px; }

/* --- header ------------------------------------------------------------- */
.topbar {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding: 14px var(--gap);
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  backdrop-filter: saturate(1.4) blur(12px);
  border-bottom: 1px solid var(--line);
}
/* The wordmark. Markup and rules live in amida-tokens.css — this only sizes
   it for the navbar and kills the link underline. Per the brand rules: never
   re-type the aleph as a Latin A, never swap the typeface, no container or
   shadow around it. */
.brand { text-decoration: none; font-size: 24px; flex-shrink: 0; }
/* font-size:inherit is load-bearing, not tidiness. amida-tokens.css sets
   `.amida-logo { font-size: 76px }` — correct for the standalone lockup, and
   its own comment says "set this; everything else scales in em", i.e. the
   consumer is expected to override it ON .amida-logo.

   Setting 24px on .brand does not do that: the parent's font-size is simply
   ignored by a child with its own absolute value. So the navbar wordmark
   rendered at 76px on every page and the sticky topbar was 110px tall —
   roughly a fifth of a phone screen, permanently, above every screen in the
   app. It read as "big brand moment" rather than "bug", which is why it
   survived. */
.brand .amida-logo { padding: 0; font-size: inherit; }

/* --- nav ---------------------------------------------------------------- */
/* On a phone the nav scrolls horizontally rather than wrapping or collapsing
   into a hamburger: five items fit in one swipe, and a menu you have to open
   hides the whole shape of the product behind a tap. */
.nav {
  display: flex; gap: 4px; align-items: center;
  overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
  margin: 0 4px; flex: 1;
}
.nav::-webkit-scrollbar { display: none; }
.nav-link {
  padding: 8px 12px; border-radius: var(--radius-pill); white-space: nowrap;
  font: 600 14px/1 var(--font); color: var(--ink-soft); text-decoration: none;
}
.nav-link:hover { color: var(--ink); }
.nav-link[aria-current="page"] {
  background: var(--accent-wash); color: var(--accent-ink);
}
.nav-end { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }

@media (max-width: 640px) {
  .topbar { gap: 6px; padding: 10px 12px; }
  .brand { font-size: 20px; }
  .nav-link { padding: 7px 9px; font-size: 13px; }
  /* On a phone the chrome keeps the avatar and Invite; Sign out lives on the
     profile page, where someone actually goes looking for it. */
  .nav-end .btn--quiet { display: none; }
}

/* --- filter bar (feed) --------------------------------------------------- */
.filters {
  display: flex; gap: 8px; align-items: center;
  overflow-x: auto; scrollbar-width: none; padding: 2px 0 10px;
}
.filters::-webkit-scrollbar { display: none; }
.filter {
  padding: 8px 14px; border-radius: var(--radius-pill); cursor: pointer;
  border: 1px solid var(--line); background: var(--card); color: var(--ink-soft);
  font: 600 13px/1 var(--font); white-space: nowrap; flex-shrink: 0;
}
.filter[aria-pressed="true"] {
  background: var(--accent-wash); color: var(--accent-ink); border-color: var(--accent);
}
.feed-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin: 20px 0 6px;
}
.feed-head h1 {
  font-family: var(--font-display); font-weight: 400;
  font-size: 25px; margin: 0;
}
.tagrow { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 9px; }
.tagchip {
  font-size: 11px; padding: 3px 9px; border-radius: var(--radius-pill);
  background: var(--accent-wash); color: var(--accent-ink); font-weight: 600;
}

/* --- cards -------------------------------------------------------------- */
.card {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow);
  padding: 18px; margin: 14px 0;
}
.card h2 { font-size: 17px; margin: 0 0 6px; line-height: 1.35; }
.card p  { margin: 0 0 10px; color: var(--ink-soft); }

.meta { display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
        font-size: 13px; color: var(--ink-faint); }

/* --- the degree chip: the one piece of UI that IS the product ------------ */
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 10px; border-radius: var(--radius-pill);
  font-size: 12px; font-weight: 600; letter-spacing: .01em;
  background: var(--accent-wash); color: var(--accent-ink);
  border: 1px solid color-mix(in srgb, var(--accent) 22%, transparent);
}
.chip--far  { background: transparent; color: var(--ink-faint);
              border-color: var(--line); }
.chip--spots{ background: color-mix(in srgb, var(--good) 12%, transparent);
              color: var(--good); border-color: color-mix(in srgb, var(--good) 28%, transparent); }
.chip--full { background: transparent; color: var(--ink-faint); border-color: var(--line); }

/* --- kind marker -------------------------------------------------------- */
.kind { font-size: 12px; text-transform: uppercase; letter-spacing: .09em;
        font-weight: 700; color: var(--accent); }

/* --- buttons ------------------------------------------------------------ */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--tap); padding: 0 20px; gap: 8px;
  border: 1px solid transparent; border-radius: var(--radius-pill);
  background: var(--accent); color: #fff;
  font: 600 15px/1 var(--font); cursor: pointer; text-decoration: none;
  transition: transform .06s ease, opacity .15s ease;
}
.btn:active { transform: scale(.98); }
.btn[disabled] { opacity: .45; cursor: not-allowed; }
.btn--ghost { background: transparent; color: var(--ink);
              border-color: var(--line); }
.btn--quiet { background: transparent; color: var(--ink-soft);
              border-color: transparent; padding: 0 10px; }
.btn--wide  { width: 100%; }
.btn--sm    { min-height: 34px; padding: 0 13px; font-size: 13px; }
.btn-row { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 14px; }

/* --- forms -------------------------------------------------------------- */
label { display: block; font-size: 13px; font-weight: 600;
        color: var(--ink-soft); margin: 14px 0 6px; }
input, textarea, select {
  width: 100%; min-height: var(--tap); padding: 11px 14px;
  font: 16px/1.4 var(--font);      /* 16px or iOS zooms on focus */
  color: var(--ink); background: var(--card);
  border: 1px solid var(--line); border-radius: 12px;
}
input:focus, textarea:focus, select:focus {
  outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent);
  outline-offset: 1px; border-color: var(--accent);
}
textarea { min-height: 96px; resize: vertical; }

/* --- feedback ----------------------------------------------------------- */
.note   { font-size: 14px; padding: 12px 14px; border-radius: 12px;
          border: 1px solid var(--line); background: var(--card); margin: 12px 0; }
.note--ok  { border-color: color-mix(in srgb, var(--good) 35%, transparent);
             color: var(--good); }
.note--bad { border-color: color-mix(in srgb, var(--accent) 35%, transparent);
             color: var(--accent-ink); }
.empty { text-align: center; color: var(--ink-faint); padding: 56px 20px; }
.empty h2 { font-family: var(--font-display); color: var(--ink-soft);
            font-weight: 500; }

.skeleton { background: var(--line); border-radius: 8px;
            animation: pulse 1.4s ease-in-out infinite; }
@keyframes pulse { 0%,100% { opacity: .5 } 50% { opacity: .9 } }

/* --- sheets: the app's one modal ----------------------------------------
   A real <dialog>, not a div with a z-index. The browser gives us the top
   layer, a backdrop, Esc-to-dismiss, inert background content and a focus
   trap for free — and `method="dialog"` returns focus to the control that
   opened the sheet, which is the thing hand-rolled modals always forget.

   Mobile-first, and here that is a real decision rather than a default: on a
   phone the sheet rises from the bottom edge, where the thumb already is. A
   centred box on a 375px screen is a box with nowhere to go. Above 640px it
   becomes a centred card, because at that width a strip pinned to the bottom
   of a tall window reads as a cookie banner.

   Replaces confirm()/prompt(). Those can't be styled, can't be themed, can't
   validate, and on iOS they say "localhost:8001 says" — which is the app
   admitting it is a web page at the exact moment it is asking for trust. */
.sheet {
  padding: 0; border: 0; background: transparent; color: var(--ink);
  width: 100%; max-width: 100%; max-height: 100dvh;
  margin: auto auto 0;                    /* bottom of the viewport */
}
.sheet::backdrop {
  background: oklch(0.25 0.03 40 / .5);
  backdrop-filter: blur(2px);
}
.sheet__panel {
  background: var(--card);
  border-top: 1px solid var(--line);
  border-radius: var(--radius) var(--radius) 0 0;
  padding: 8px var(--gap) calc(18px + env(safe-area-inset-bottom));
  max-height: 88dvh; overflow-y: auto;
  box-shadow: 0 -8px 40px oklch(0.25 0.03 40 / .18);
}
.sheet__panel:focus { outline: none; }
.sheet__grip {
  width: 38px; height: 4px; border-radius: 999px; background: var(--line);
  margin: 4px auto 14px;
}
.sheet__title {
  font-family: var(--font-display); font-weight: 400;
  font-size: 21px; line-height: 1.25; margin: 0 0 6px;
}
.sheet__intro { color: var(--ink-soft); font-size: 15px; margin: 0 0 14px; }
.sheet__label { font-size: 13px; font-weight: 600; color: var(--ink-soft);
                margin: 14px 0 8px; }

/* Options are labels wrapping a radio, so the whole row is the target — a
   44px row you can hit anywhere, not a 13px dot you have to aim at. */
.sheet__opt {
  display: flex; gap: 11px; align-items: flex-start;
  min-height: var(--tap); padding: 11px 13px; margin: 0 0 8px;
  border: 1px solid var(--line); border-radius: 12px;
  background: var(--card); cursor: pointer;
  font-size: 15px; font-weight: 400; color: var(--ink);
}
.sheet__opt:has(input:checked) {
  border-color: var(--accent); background: var(--accent-wash);
  color: var(--accent-ink);
}
.sheet__opt:has(input:focus-visible) {
  outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent);
  outline-offset: 1px;
}
/* the global input rule is full-width and 44px tall — undo it for a radio */
.sheet__opt input {
  width: auto; min-height: 0; margin: 2px 0 0; padding: 0;
  flex-shrink: 0; accent-color: var(--accent);
}
.sheet__opt-label { display: block; font-weight: 600; }
.sheet__opt-hint  { display: block; font-size: 13px; color: var(--ink-faint);
                    font-weight: 400; margin-top: 1px; }
.sheet__opt:has(input:checked) .sheet__opt-hint { color: var(--accent-ink); opacity: .8; }

/* Password + its reveal toggle. The toggle sits inside the field's box rather
   than beside it so the input keeps the full column width — a password box
   noticeably narrower than every other input reads as a different kind of
   thing, which is the opposite of reassuring. */
.sheet__pw { position: relative; display: flex; align-items: center; }
.sheet__pw input { padding-right: 74px; }
.sheet__reveal {
  position: absolute; right: 6px;
  min-height: 32px; padding: 0 11px;
  border: 0; border-radius: var(--radius-pill);
  background: transparent; color: var(--ink-soft);
  font: 600 13px/1 var(--font); cursor: pointer;
}
.sheet__reveal:hover { color: var(--accent-ink); background: var(--accent-wash); }
.sheet__reveal:focus-visible {
  outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent);
  outline-offset: 1px;
}

.sheet__error {
  font-size: 14px; color: var(--accent-ink); margin: 10px 0 0;
  padding: 9px 12px; border-radius: 10px;
  border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
}
/* The confirming action sits FIRST on a phone: it is under the thumb, and the
   way out of a sheet is already Esc, the backdrop, and the swipe-down grip. */
.sheet__actions { display: flex; flex-direction: column; gap: 8px; margin-top: 18px; }
.sheet__actions .btn { width: 100%; }

@keyframes sheet-rise {
  from { transform: translateY(14px); opacity: .4 }
  to   { transform: none; opacity: 1 }
}
.sheet[open] .sheet__panel { animation: sheet-rise .2s cubic-bezier(.2,.8,.3,1); }

@media (prefers-reduced-motion: reduce) {
  .sheet[open] .sheet__panel { animation: none; }
}

@media (min-width: 640px) {
  .sheet { margin: auto; max-width: 440px; }
  .sheet__panel {
    border: 1px solid var(--line); border-radius: var(--radius);
    padding: 20px 22px 22px; box-shadow: var(--shadow);
  }
  .sheet__grip { display: none; }
  /* room to spread out, so the actions sit on one line, confirm on the right
     where a pointer expects it */
  .sheet__actions { flex-direction: row-reverse; justify-content: flex-start; }
  .sheet__actions .btn { width: auto; }
}

/* --- bottom nav: thumbs, not cursors ------------------------------------ */
.tabbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
  display: flex; justify-content: space-around;
  padding: 8px 0 calc(8px + env(safe-area-inset-bottom));
  background: color-mix(in srgb, var(--paper) 92%, transparent);
  backdrop-filter: blur(12px); border-top: 1px solid var(--line);
}
.tabbar a {
  flex: 1; min-height: var(--tap);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px; font-size: 11px; font-weight: 600;
  color: var(--ink-faint); text-decoration: none;
}
.tabbar a[aria-current="page"] { color: var(--accent); }
.tabbar svg { width: 22px; height: 22px; }

.hidden { display: none !important; }

/* The `hidden` ATTRIBUTE, made to actually work.

   The UA stylesheet's `[hidden] { display: none }` is a plain attribute
   selector, so any class that sets display beats it — `.btn` is
   `display:inline-flex`, which means `<button class="btn" hidden>` renders
   perfectly visibly. It fails silently and only on styled elements, which is
   the worst combination to debug.

   Worth having alongside `.hidden` rather than instead of it: the attribute
   also removes the element from the accessibility tree, so a control hidden
   this way is gone for a screen reader too, not just visually. */
[hidden] { display: none !important; }

@media (min-width: 720px) {
  .wrap { padding-bottom: var(--gap); }
  .tabbar { position: static; border: 1px solid var(--line);
            border-radius: var(--radius-pill); max-width: var(--max);
            margin: 0 auto 24px; }
}
