/* ============================================================================
   Owner portal — visual system.
   Nothing here is framework-imposed; these are plain templates and plain CSS.
   Per-instance branding supplies RAW brand values (--brand-*, --masthead);
   this file decides how each mode uses them. That way a property keeps its
   identity in dark mode instead of every portal collapsing to one accent.
   ========================================================================= */

:root {
  /* Neutrals carry a slight warm-slate cast so they read as chosen, not default */
  --bg:            var(--brand-ground);
  --surface:       #ffffff;
  --surface-2:     #fbfaf8;
  --ink:           #1a1f21;
  --ink-2:         #48555a;
  /* Muted, but still text people have to read — dates, meta lines, labels.
     The old #7d8b90 sat at 3.2:1 on every one of the three brand grounds,
     under the 4.5:1 floor for text this size. Owners here skew older. */
  --ink-3:         #5f6d71;
  --line:          #e3e0da;
  --line-strong:   #d2cec6;

  /* Supplied per instance from the environment; these are the fallbacks. */
  --brand-accent:      #0f5f6b;
  --brand-accent-deep: #0b474f;
  --brand-ground:      #f7f6f3;
  --masthead:          #1f2a2c;
  --logo-h:            40px;
  /* The sticky masthead's height: 16px padding top and bottom, a 1px rule,
     and whichever is taller — the property's logo or the account button (the
     32px avatar plus its 3px padding and 1px border). Derived rather than
     fixed because the three logos are three different heights. */
  --header-h:          calc(max(var(--logo-h), 40px) + 35px);
  /* The browse panel is barely a tint — the separation comes from the rule
     down its edge, not from weight. A darker panel made the page feel heavy. */
  --panel:             color-mix(in srgb, var(--brand-ground) 97%, var(--ink));

  --accent:        var(--brand-accent);
  --accent-deep:   var(--brand-accent-deep);
  --accent-wash:   color-mix(in srgb, var(--brand-accent) 8%, transparent);

  --good:          #1c7a4e;
  --good-wash:     rgba(28, 122, 78, .1);
  --warn:          #9a5b12;
  --bad:           #a3231a;
  --bad-wash:      rgba(163, 35, 26, .1);

  --r-sm: 8px;
  --r:    12px;
  --r-lg: 18px;

  --shadow-sm: 0 1px 2px rgba(26, 31, 33, .05);
  --shadow:    0 1px 3px rgba(26, 31, 33, .06), 0 8px 24px -12px rgba(26, 31, 33, .18);
  --shadow-lg: 0 2px 6px rgba(26, 31, 33, .07), 0 18px 44px -18px rgba(26, 31, 33, .28);

  --serif: "Newsreader", Georgia, "Times New Roman", serif;
  --sans:  "Public Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono:  ui-monospace, SFMono-Regular, Menlo, monospace;
  /* Overridden per property; falls back to the accessible accent. */
  --vivid: var(--brand-accent);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg:          #101416;
    --surface:     #171d20;
    /* The light-mode panel is derived from the brand paper, which never
       flips — left alone it stays light under dark-mode text and the browse
       strip renders white-on-cream. A step above the dark ground instead. */
    --panel:       #1a2124;
    --surface-2:   #1c2326;
    --ink:         #eef1f1;
    --ink-2:       #aab8bc;
    --ink-3:       #7d8e93;
    --line:        #2a3336;
    --line-strong: #3a4549;
    /* The brand accent is mixed toward white so it carries on a dark ground
       and still reads as this property's colour rather than a shared one. */
    --accent:      color-mix(in srgb, var(--brand-accent) 55%, #ffffff);
    --accent-deep: color-mix(in srgb, var(--brand-accent) 34%, #ffffff);
    --accent-wash: color-mix(in srgb, var(--brand-accent) 22%, transparent);
    --good:        #4ade80;
    --good-wash:   rgba(74, 222, 128, .13);
    --warn:        #e0a44a;
    --bad:         #f87462;
    --bad-wash:    rgba(248, 116, 98, .13);
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, .3);
    --shadow:    0 1px 3px rgba(0, 0, 0, .4), 0 8px 24px -12px rgba(0, 0, 0, .6);
    --shadow-lg: 0 2px 6px rgba(0, 0, 0, .45), 0 18px 44px -18px rgba(0, 0, 0, .7);
  }
}

/* The Shore Club's own display face, self-hosted from their site with the
   owner's go-ahead. Only loaded by the instance whose --serif names it. */
@font-face {
  font-family: "OptimaLTStd";
  src: url("fonts/optima-regular.woff2") format("woff2"),
       url("fonts/optima-regular.woff") format("woff");
  font-weight: 400; font-style: normal; font-display: swap;
}

* { box-sizing: border-box; }

/* The hidden attribute has to beat any display rule we set elsewhere —
   .field is display:grid and .checkline is inline-flex, so without this a
   [hidden] element on either stays on screen. */
[hidden] { display: none !important; }

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

a { color: var(--accent-deep); }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}

.wrap { width: 100%; max-width: 1020px; margin: 0 auto; padding: 0 20px; }

/* ---------- header ---------------------------------------------------- */

/* ---------- masthead ---------------------------------------------------
   A dark field, because every property's logo is white-only — there is no
   dark variant of any of them, so a pale header would have nothing to show.
   The depth of the dark is per-property; the structure is not. */
.site-header {
  position: sticky; top: 0; z-index: 20;
  background: var(--masthead);
  /* The resort's full-strength colour, drawn as a rule along the masthead.
     It cannot carry white text at this saturation, but on the dark bar it
     reads clearly and is unmistakably the property's own. */
  border-bottom: 3px solid var(--vivid);
}
.header-inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: 20px; padding-top: 16px; padding-bottom: 16px;
}
.brand { display: flex; align-items: center; gap: 14px; text-decoration: none; min-width: 0; }
.brand-mark {
  height: var(--logo-h, 40px); width: auto; max-width: 260px; display: block;
  /* The marks were drawn for photography, where pure white is right. On a
     flat field it glares, so it is eased back a touch. */
  opacity: .94;
}
.brand-word {
  font-family: var(--serif); font-size: 21px; font-weight: 500;
  color: #fff; letter-spacing: -.01em;
}
.brand-sub {
  font-family: var(--sans); font-size: 10.5px; font-weight: 500;
  letter-spacing: .18em; text-transform: uppercase;
  color: rgba(255, 255, 255, .58);
  padding-left: 14px; border-left: 1px solid rgba(255, 255, 255, .18);
  white-space: nowrap;
}
@media (max-width: 620px) {
  .brand-sub { display: none; }
  .brand-mark { height: calc(var(--logo-h, 40px) * .8); }
}

.nav-burger { display: none; }
.header-right { display: flex; align-items: center; gap: 2px; }
.site-nav { display: flex; align-items: center; gap: 2px; flex-wrap: wrap; }
.site-nav a, .linklike {
  color: rgba(255, 255, 255, .74); text-decoration: none;
  font-size: 11.5px; font-weight: 600; letter-spacing: .11em; text-transform: uppercase;
  padding: 9px 13px; border-radius: var(--r-sm);
  transition: color .15s, background .15s;
}
.site-nav a:hover, .linklike:hover { color: #fff; background: rgba(255, 255, 255, .09); }
.site-nav a.is-active { color: var(--vivid); background: rgba(255, 255, 255, .1); }
.logout-form { margin: 0; display: inline; }
.linklike { background: none; border: 0; cursor: pointer; font-family: inherit; }

/* ---------- page furniture -------------------------------------------- */

main.wrap { flex: 1; padding-top: 36px; padding-bottom: 64px; }

.page-head { margin-bottom: 26px; }
h1 {
  font-family: var(--serif);
  font-size: clamp(28px, 4vw, 36px);
  font-weight: 500; letter-spacing: -.015em; line-height: 1.15;
  margin: 0 0 6px; text-wrap: balance;
}
.page-sub { margin: 0; color: var(--ink-2); font-size: 16px; }

h2 { font-family: var(--serif); font-weight: 500; letter-spacing: -.01em; }
.sub-head { font-size: 21px; margin: 34px 0 12px; }

.muted { color: var(--ink-2); }
.small { font-size: 14px; }
.mono { font-family: var(--mono); font-size: 13px; }

/* ---------- controls --------------------------------------------------- */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  padding: 10px 18px;
  background: var(--accent); color: #fff;
  border: 1px solid var(--accent); border-radius: var(--r-sm);
  font: inherit; font-size: 14.5px; font-weight: 600; line-height: 1.2;
  text-decoration: none; cursor: pointer; white-space: nowrap;
  transition: background .15s, border-color .15s, transform .06s, box-shadow .15s;
  box-shadow: var(--shadow-sm);
}
.btn:hover { background: var(--accent-deep); border-color: var(--accent-deep); }
.btn:active { transform: translateY(1px); }
.btn.ghost {
  background: var(--surface); color: var(--ink-2); border-color: var(--line-strong);
  box-shadow: none; font-weight: 500;
}
.btn.ghost:hover { background: var(--surface-2); color: var(--accent-deep); border-color: var(--accent); }

input[type="text"], input[type="search"], input[type="email"],
input[type="password"], input[type="date"], select, textarea {
  padding: 11px 14px;
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--line-strong); border-radius: var(--r-sm);
  font: inherit; font-size: 15px; width: 100%;
  transition: border-color .15s, box-shadow .15s;
}
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-wash);
}
::placeholder { color: var(--ink-3); }

/* search + filter bar */
.toolbar { display: grid; gap: 12px; margin-bottom: 18px; }
.search-row { display: flex; gap: 10px; flex-wrap: wrap; }
.search-field { position: relative; flex: 1 1 260px; min-width: 0; }
.search-field input { padding-left: 40px; }
.search-field svg {
  position: absolute; left: 13px; top: 50%; transform: translateY(-50%);
  color: var(--ink-3); pointer-events: none;
}

/* category chips — tappable, scrollable on small screens */
.chips { display: flex; gap: 8px; flex-wrap: wrap; }
.chip {
  display: inline-block; padding: 6px 14px;
  background: var(--surface); color: var(--ink-2);
  border: 1px solid var(--line-strong); border-radius: 999px;
  font-size: 13.5px; font-weight: 500; text-decoration: none;
  transition: all .15s; white-space: nowrap;
}
.chip:hover { border-color: var(--accent); color: var(--accent-deep); }
.chip.is-on {
  background: var(--accent); border-color: var(--accent); color: #fff;
}

.result-line { color: var(--ink-2); font-size: 14px; margin: 0 0 14px; }

/* ---------- document list --------------------------------------------- */

.doc-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }

/* A library entry is a folder (<details>) or a lone document (a one-item list,
   whose own `gap` therefore never applies). Only the folder carried a margin,
   so single documents sat flush against whatever followed. Space them at the
   container instead, where both kinds are treated alike. */
.year-block > .doc-list,
.more-body > .doc-list { margin-bottom: 10px; }

.doc {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 16px; align-items: center;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 16px 18px;
  box-shadow: var(--shadow-sm);
  transition: border-color .15s, box-shadow .15s, transform .12s;
}
.doc:hover {
  border-color: var(--line-strong);
  box-shadow: var(--shadow);
  transform: translateY(-1px);
}

/* file-type badge — lets the eye sort the list at a glance */
.ftype {
  width: 44px; height: 52px; flex: none;
  display: grid; place-items: center;
  border-radius: var(--r-sm);
  font-family: var(--mono); font-size: 10.5px; font-weight: 600;
  letter-spacing: .04em; text-transform: uppercase;
  background: var(--accent-wash); color: var(--accent-deep);
  border: 1px solid color-mix(in srgb, var(--accent) 22%, transparent);
}
.ftype.pdf { background: var(--bad-wash); color: var(--bad);
  border-color: color-mix(in srgb, var(--bad) 24%, transparent); }
.ftype.doc { background: rgba(31, 95, 139, .1); color: #1f5f8b;
  border-color: rgba(31, 95, 139, .24); }
.ftype.xls { background: var(--good-wash); color: var(--good);
  border-color: color-mix(in srgb, var(--good) 24%, transparent); }

.doc-main { min-width: 0; }
.doc-title {
  font-family: var(--serif); font-size: 18px; font-weight: 500;
  letter-spacing: -.005em; margin: 0 0 3px; line-height: 1.3;
}
.doc-title a { color: var(--ink); text-decoration: none; }
.doc-title a:hover { color: var(--accent-deep); }
.doc-summary {
  margin: 0 0 7px; color: var(--ink-2); font-size: 14.5px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.doc-meta {
  margin: 0; display: flex; flex-wrap: wrap; gap: 8px 14px;
  color: var(--ink-3); font-size: 13px; align-items: center;
}
.tag {
  background: var(--surface-2); color: var(--ink-2);
  border: 1px solid var(--line); border-radius: 999px;
  padding: 2px 10px; font-size: 12px; font-weight: 500;
}
.doc-actions { display: flex; gap: 8px; flex-wrap: wrap; justify-content: flex-end; }

@media (max-width: 640px) {
  .doc { grid-template-columns: auto 1fr; }
  .doc-actions { grid-column: 1 / -1; justify-content: flex-start; }
}

/* ---------- empty state ------------------------------------------------ */

.empty-state {
  text-align: center; padding: 56px 24px;
  background: var(--surface); border: 1px dashed var(--line-strong);
  border-radius: var(--r-lg); color: var(--ink-2);
}
.empty-state svg { color: var(--ink-3); margin-bottom: 12px; }
.empty-state h2 { font-size: 20px; margin: 0 0 6px; color: var(--ink); }
.empty-state p { margin: 0 0 14px; }

/* ---------- pagination -------------------------------------------------- */

.pager {
  display: flex; align-items: center; justify-content: center;
  gap: 14px; margin-top: 28px; flex-wrap: wrap;
}
.pager .page-of { color: var(--ink-2); font-size: 14px; font-variant-numeric: tabular-nums; }

/* ---------- cards / panels --------------------------------------------- */

.panel {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 24px; box-shadow: var(--shadow-sm);
}

.auth-card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 34px 32px;
  max-width: 430px; margin: 40px auto; box-shadow: var(--shadow-lg);
}
.auth-card h1 { font-size: 27px; margin-bottom: 8px; }
.auth-card .page-sub { margin-bottom: 22px; font-size: 15px; }
.stack { display: grid; gap: 14px; }
.field { display: grid; gap: 6px; }
.field label { font-size: 13.5px; font-weight: 600; color: var(--ink-2); }
.stack .btn { margin-top: 4px; width: 100%; padding: 12px 18px; font-size: 15px; }
.auth-foot { margin: 20px 0 0; text-align: center; font-size: 14px; color: var(--ink-2); }

/* ---------- stats + tables --------------------------------------------- */

.stat-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 12px; margin-bottom: 22px; }
.stat {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r); padding: 16px 18px; box-shadow: var(--shadow-sm);
}
.stat-n { display: block; font-family: var(--serif); font-size: 30px;
  font-weight: 500; line-height: 1.1; font-variant-numeric: tabular-nums; }
.stat-l { display: block; font-size: 12.5px; color: var(--ink-3);
  letter-spacing: .06em; text-transform: uppercase; font-weight: 500; margin-top: 3px; }
.stat-warn .stat-n { color: var(--bad); }

.table-wrap {
  overflow-x: auto; border: 1px solid var(--line);
  border-radius: var(--r); background: var(--surface); box-shadow: var(--shadow-sm);
}
table.data { border-collapse: collapse; width: 100%; min-width: 540px; font-size: 14.5px; }
table.data th, table.data td { text-align: left; padding: 12px 16px; border-bottom: 1px solid var(--line); }
table.data th {
  font-size: 11.5px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink-3); background: var(--surface-2); font-weight: 600; white-space: nowrap;
}
table.data tr:last-child td { border-bottom: none; }
table.data tbody tr { transition: background .12s; }
table.data tbody tr:hover { background: var(--surface-2); }
td.num { font-variant-numeric: tabular-nums; }

.pill {
  display: inline-block; padding: 3px 10px; border-radius: 999px;
  font-size: 12px; font-weight: 600;
}
.pill.ok  { background: var(--good-wash); color: var(--good); }
.pill.bad { background: var(--bad-wash); color: var(--bad); }

.checkline { display: inline-flex; align-items: center; gap: 7px;
  font-size: 14px; color: var(--ink-2); white-space: nowrap; }
.checkline input { width: auto; }

/* ---------- detail ------------------------------------------------------ */

.crumb { margin: 0 0 16px; font-size: 14px; }
.crumb a { color: var(--ink-2); text-decoration: none; font-weight: 500; }
.crumb a:hover { color: var(--accent-deep); }
.lede { font-size: 17px; color: var(--ink-2); max-width: 68ch; line-height: 1.65; }

.detail-head { display: flex; gap: 18px; align-items: flex-start; margin-bottom: 8px; }
.detail-head .ftype { width: 56px; height: 66px; font-size: 12px; }

/* ---------- messages ---------------------------------------------------- */

.flash {
  background: var(--accent-wash); border: 1px solid color-mix(in srgb, var(--accent) 25%, transparent);
  border-radius: var(--r); padding: 12px 16px; margin: 0 0 16px; color: var(--ink);
}
.error { color: var(--bad); font-size: 14px; margin: 0; }
ul.error { padding-left: 18px; }

/* ---------- footer ------------------------------------------------------ */

/* Mirrors the masthead — same field, same vivid rule, facing it. */
.site-footer {
  display: flex; flex-direction: column; align-items: center; gap: 14px;
  background: var(--masthead);
  border-top: 3px solid var(--vivid);
  padding: 34px 20px 26px;
}
.footer-brand { display: block; }
.footer-mark {
  display: block; height: calc(var(--logo-h, 40px) * .8); width: auto;
  max-width: 220px; opacity: .94;
}
.footer-word {
  font-family: var(--serif); font-size: 19px; font-weight: 500; color: #fff;
}
.footer-meta { display: flex; align-items: center; gap: 16px; }
.footer-ver { font-size: 11px; color: rgba(255, 255, 255, .38); letter-spacing: .04em; }

/* The staff/owner rendering switch. */
.viewswitch-form { margin: 0; }
.viewswitch {
  display: inline-flex; align-items: center; gap: 9px;
  min-height: 32px; padding: 0 2px;
  background: none; border: 0; cursor: pointer; font: inherit;
}
.vs-label {
  font-size: 10.5px; font-weight: 600; letter-spacing: .13em;
  text-transform: uppercase; color: rgba(255, 255, 255, .55);
}
.viewswitch.is-on .vs-label { color: var(--vivid); }
.vs-track {
  position: relative; width: 32px; height: 18px; border-radius: 999px;
  background: rgba(255, 255, 255, .22); transition: background .15s;
}
.viewswitch.is-on .vs-track { background: var(--vivid); }
.vs-knob {
  position: absolute; top: 2px; left: 2px; width: 14px; height: 14px;
  border-radius: 50%; background: #fff; transition: transform .15s;
}
.viewswitch.is-on .vs-knob { transform: translateX(14px); }
.viewswitch:focus-visible { outline: 2px solid var(--vivid); outline-offset: 3px; border-radius: 6px; }

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* ============================ document browser ========================== */

.browser-bar {
  position: sticky; top: 64px; z-index: 10;
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  backdrop-filter: saturate(180%) blur(10px);
  padding: 12px 0 14px; margin-bottom: 6px;
  display: grid; gap: 12px;
  border-bottom: 1px solid transparent;
}
.browser-bar .search-field input { padding-right: 38px; }
.clear-btn {
  position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
  width: 26px; height: 26px; border: 0; border-radius: 50%;
  background: var(--line); color: var(--ink-2);
  font-size: 17px; line-height: 1; cursor: pointer;
}
.clear-btn:hover { background: var(--line-strong); color: var(--ink); }

.year-block { margin-bottom: 28px; }
.year-label {
  /* Flex on the base rule, not only on the coloured variant: the count uses
     margin-left:auto to sit at the right, which silently did nothing in the
     date view and left headings reading "2026 1". */
  display: flex; align-items: baseline; gap: 10px;
  font-family: var(--mono); font-size: 12px; font-weight: 600;
  letter-spacing: .16em; color: var(--ink-3);
  margin: 0 0 10px; padding-bottom: 7px;
  border-bottom: 1px solid var(--line);
}

/* --- collection "folder" --- */
.folder {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r); margin-bottom: 10px;
  box-shadow: var(--shadow-sm); overflow: hidden;
  transition: border-color .15s, box-shadow .15s;
}
.folder:hover { border-color: var(--line-strong); box-shadow: var(--shadow); }
.folder[open] { border-color: color-mix(in srgb, var(--accent) 32%, var(--line)); }

.folder-head {
  display: flex; align-items: center; gap: 14px;
  padding: 15px 18px; cursor: pointer; list-style: none;
  user-select: none;
}
.folder-head::-webkit-details-marker { display: none; }
.folder-icon {
  width: 38px; height: 38px; flex: none; display: grid; place-items: center;
  border-radius: var(--r-sm);
  background: var(--accent-wash); color: var(--accent-deep);
}
.folder-main { flex: 1; min-width: 0; }
.folder-title {
  display: block; font-family: var(--serif); font-size: 18px;
  font-weight: 500; letter-spacing: -.005em; line-height: 1.3;
}
.folder-meta { display: block; font-size: 13px; color: var(--ink-3); margin-top: 1px; }
.folder-chev { color: var(--ink-3); flex: none; transition: transform .18s ease; }
.folder[open] .folder-chev { transform: rotate(180deg); }

.doc-list.inside {
  border-top: 1px solid var(--line);
  background: var(--surface-2);
  padding: 10px 12px; gap: 8px;
}
.doc-list.inside .doc {
  background: var(--surface); box-shadow: none; padding: 12px 14px;
}
.doc-list.inside .doc:hover { transform: none; }
.doc-list.inside .doc-title { font-size: 16px; }

.folder[open] .doc-list.inside { animation: unfold .18s ease; }
@keyframes unfold { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; } }

/* --- preview --- */
.preview-frame {
  width: 100%; height: min(78vh, 900px);
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--surface-2); margin-top: 20px;
}

/* ============================ back office ============================== */

.nav-divider {
  width: 1px; height: 16px; background: rgba(255, 255, 255, .2);
  margin: 0 8px; display: inline-block;
}

/* --- dropzone --- */
.dropzone {
  border: 2px dashed var(--line-strong); border-radius: var(--r-lg);
  background: var(--surface); padding: 46px 24px; text-align: center;
  color: var(--ink-2); cursor: pointer; transition: all .16s;
}
.dropzone:hover, .dropzone:focus-visible {
  border-color: var(--accent); background: var(--accent-wash);
}
.dropzone.is-over {
  border-color: var(--accent); background: var(--accent-wash);
  transform: scale(1.005); box-shadow: var(--shadow);
}
.dropzone.compact { padding: 20px; }
.dropzone.compact svg, .dropzone.compact .dz-sub { display: none; }
.dropzone svg { color: var(--ink-3); margin-bottom: 10px; }
.dz-main { font-size: 17px; margin: 0 0 4px; color: var(--ink); }
.dz-link { color: var(--accent-deep); font-weight: 600; text-decoration: underline; }
.dz-sub { margin: 0; font-size: 13.5px; color: var(--ink-3); }

/* --- batch panel --- */
.batch-panel { margin-top: 20px; }
.batch-grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: 14px;
}
.batch-grid .span-2 { grid-column: 1 / -1; }
@media (max-width: 620px) { .batch-grid { grid-template-columns: 1fr; } }
.hint { margin: 8px 0 0; font-size: 13.5px; color: var(--ink-3);
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.hint select { width: auto; flex: 1 1 200px; }

.count-badge {
  display: inline-block; min-width: 24px; padding: 1px 8px;
  background: var(--accent-wash); color: var(--accent-deep);
  border-radius: 999px; font-family: var(--sans); font-size: 13px;
  font-weight: 600; vertical-align: middle;
}

/* --- people --- */
.password-reveal {
  display: flex; gap: 16px; align-items: center; justify-content: space-between;
  flex-wrap: wrap;
  background: var(--good-wash); border: 1px solid color-mix(in srgb, var(--good) 32%, transparent);
  border-radius: var(--r); padding: 16px 18px; margin-bottom: 20px;
}
.pw-label { margin: 0 0 6px; font-size: 13.5px; color: var(--ink-2); }
.pw-value {
  font-family: var(--mono); font-size: 19px; font-weight: 600; letter-spacing: .04em;
  background: var(--surface); border: 1px solid var(--line);
  padding: 7px 14px; border-radius: var(--r-sm); display: inline-block; user-select: all;
}

.add-person { margin-bottom: 20px; }
.add-person-body { padding: 4px 18px 20px; border-top: 1px solid var(--line); }
.add-person-body form { padding-top: 16px; }
.method-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin: 18px 0; }
@media (max-width: 620px) { .method-row { grid-template-columns: 1fr; } }
.method {
  display: flex; gap: 10px; align-items: flex-start; padding: 14px;
  border: 1px solid var(--line-strong); border-radius: var(--r);
  background: var(--surface); cursor: pointer; font-size: 14.5px;
}
.method:hover { border-color: var(--accent); }
.method input { width: auto; margin-top: 3px; }
.method:has(input:checked) { border-color: var(--accent); background: var(--accent-wash); }

.people-table .person-name { font-weight: 600; display: block; }
.people-table .person-user { font-family: var(--mono); font-size: 12px; color: var(--ink-3); }
.people-table td { vertical-align: middle; }
.people-table td.small { word-break: break-word; min-width: 150px; }
.people-table tr.is-off { opacity: .55; }
.row-actions { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
.row-actions form { margin: 0; }
.mini {
  padding: 5px 10px; font-size: 12.5px; font-weight: 500;
  background: var(--surface); color: var(--ink-2);
  border: 1px solid var(--line-strong); border-radius: var(--r-sm);
  cursor: pointer; white-space: nowrap; font-family: inherit;
}
.mini:hover { border-color: var(--accent); color: var(--accent-deep); background: var(--surface-2); }
.mini.danger:hover { border-color: var(--bad); color: var(--bad); background: var(--bad-wash); }

/* ---------- board ------------------------------------------------------- */

/* (board styles live further down, with the current card design) */

/* ---------- uploader: group + file cards ------------------------------- */

.group-card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); box-shadow: var(--shadow-sm);
  margin: 18px 0; overflow: hidden;
}
.group-head { display: flex; gap: 14px; padding: 18px; align-items: flex-start; }
.group-icon {
  width: 40px; height: 40px; flex: none; display: grid; place-items: center;
  border-radius: var(--r-sm); background: var(--accent-wash); color: var(--accent-deep);
}
.group-fields { flex: 1; min-width: 0; display: grid; gap: 10px; }
.group-name-input {
  font-family: var(--serif); font-size: 21px; font-weight: 500; letter-spacing: -.01em;
  padding: 8px 12px; border-style: dashed; border-color: var(--accent);
  background: var(--accent-wash);
}
.group-name-input:focus { border-style: solid; background: var(--surface); }
.group-meta-row { display: flex; gap: 14px; align-items: center; flex-wrap: wrap; }
.inline-field {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 13px; color: var(--ink-3); font-weight: 500;
}
.inline-field input, .inline-field select { width: auto; padding: 7px 10px; font-size: 14px; }
.group-card.is-single .group-name-input,
.group-card.is-single .group-icon { display: none; }

/* file cards */
.file-grid {
  list-style: none; margin: 0; padding: 14px 18px 20px;
  border-top: 1px solid var(--line); background: var(--surface-2);
  display: grid; gap: 10px;
  grid-template-columns: repeat(auto-fill, minmax(216px, 1fr));
}
.file-card {
  position: relative; background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--r);
  padding: 14px 14px 12px; cursor: pointer;
  display: grid; gap: 8px; align-content: start;
  transition: border-color .14s, box-shadow .14s, transform .1s, opacity .14s;
}
.file-card:hover { border-color: var(--line-strong); box-shadow: var(--shadow-sm); }
.file-card:active { cursor: grabbing; }
.file-card.is-selected { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-wash); }
.file-card.is-bad { border-color: var(--bad); background: var(--bad-wash); }
.file-card.is-routed { opacity: .82; border-style: dashed; }

.fc-check {
  position: absolute; top: 10px; right: 10px;
  width: 19px; height: 19px; border-radius: 50%;
  border: 1.5px solid var(--line-strong); background: var(--surface);
  display: grid; place-items: center; color: transparent;
}
.file-card.is-selected .fc-check {
  background: var(--accent); border-color: var(--accent); color: #fff;
}
.file-card .ftype { width: 34px; height: 40px; font-size: 9.5px; }
.fc-title {
  font-size: 14px; font-weight: 500; padding: 7px 9px;
  border-color: transparent; background: var(--surface-2);
}
.fc-title:hover { border-color: var(--line); }
.fc-meta { display: flex; align-items: center; gap: 8px; justify-content: space-between; }
.fc-meta .fc-date {
  width: auto; flex: 1 1 auto; min-width: 0;
  padding: 5px 8px; font-size: 12.5px; color: var(--ink-2);
  border-color: transparent; background: var(--surface-2);
}
.fc-meta .fc-date:hover { border-color: var(--line); }
.fc-size { font-size: 11.5px; color: var(--ink-3); font-family: var(--mono); white-space: nowrap; }
.fc-foot {
  display: flex; gap: 8px; justify-content: space-between; align-items: center;
  font-size: 11.5px; color: var(--ink-3); min-height: 16px;
}
.fc-cat { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fc-target { color: var(--accent-deep); font-weight: 600; white-space: nowrap; }
.fc-remove {
  position: absolute; bottom: 8px; right: 8px;
  width: 22px; height: 22px; border-radius: 50%; border: 0;
  background: transparent; color: var(--ink-3); font-size: 16px; line-height: 1; cursor: pointer;
}
.fc-remove:hover { background: var(--bad-wash); color: var(--bad); }

/* drop targets */
.targets { display: grid; gap: 20px; margin: 22px 0 4px; }
.target-label {
  font-family: var(--sans); font-size: 12px; font-weight: 600;
  letter-spacing: .09em; text-transform: uppercase; color: var(--ink-3);
  margin: 0 0 9px; display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap;
}
.target-label .small { text-transform: none; letter-spacing: 0; font-weight: 400; }
.group-targets { display: grid; gap: 8px; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); }
.group-target {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r);
  padding: 11px 14px; display: grid; gap: 2px; transition: all .14s;
}
.gt-title { font-size: 14px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gt-meta { font-size: 12px; color: var(--ink-3); }
.group-search { margin-top: 10px; max-width: 380px; }
.group-search input { padding-left: 38px; font-size: 14px; }
.group-search svg { left: 12px; }

/* live drag affordances */
body.is-dragging .drop-target {
  border-style: dashed; border-color: var(--line-strong);
}
.drop-target.is-over {
  border-color: var(--accent) !important; background: var(--accent-wash) !important;
  color: var(--accent-deep); transform: scale(1.03);
}
.chip.drop-target { cursor: pointer; }

/* ============================== guided tour ============================= */

body.tour-active { overflow: hidden; }

/* Transparent while a target is spotlit — the spot's own shadow does the
   dimming, so the hole is genuinely clear. The overlay only paints when a
   centred panel (welcome, finale) is up. No blur anywhere: a backdrop blur
   cannot be punched through, which is how targets ended up as dim as the
   rest of the page. */
.tour-overlay {
  position: fixed; inset: 0; z-index: 900;
  background: transparent;
  animation: tour-fade .18s ease;
}
.tour-overlay.is-dim { background: rgba(12, 18, 20, .58); }
@keyframes tour-fade { from { opacity: 0; } }

/* the cut-out: a transparent box with an enormous shadow standing in for a mask */
.tour-spot {
  position: fixed; z-index: 901; pointer-events: none;
  border-radius: var(--r);
  box-shadow: 0 0 0 9999px rgba(12, 18, 20, .58),
              0 0 0 2px var(--accent),
              0 0 0 7px color-mix(in srgb, var(--accent) 28%, transparent);
  transition: all .22s cubic-bezier(.4, 0, .2, 1);
}

.tour-bubble {
  position: fixed; z-index: 902;
  width: min(360px, calc(100vw - 32px));
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
  padding: 20px 22px 18px;
  animation: tour-pop .2s cubic-bezier(.2, .9, .3, 1.3);
}
@keyframes tour-pop { from { opacity: 0; transform: scale(.96) translateY(4px); } }

.tour-bubble.is-centred {
  top: 50%; left: 50%; transform: translate(-50%, -50%);
}

/* arrow */
.tour-bubble[data-arrow="top"]::before,
.tour-bubble[data-arrow="bottom"]::before {
  content: ""; position: absolute; left: var(--arrow-x, 50%);
  width: 13px; height: 13px; background: var(--surface);
  border: 1px solid var(--line); transform: translateX(-50%) rotate(45deg);
}
.tour-bubble[data-arrow="top"]::before { top: -7px; border-right: 0; border-bottom: 0; }
.tour-bubble[data-arrow="bottom"]::before { bottom: -7px; border-left: 0; border-top: 0; }

.tb-count {
  margin: 0 0 4px; font-family: var(--mono); font-size: 11px;
  letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3);
}
.tour-bubble h2 {
  font-family: var(--serif); font-size: 20px; font-weight: 500;
  margin: 0 0 7px; letter-spacing: -.01em; line-height: 1.25;
}
.tb-body { margin: 0 0 16px; font-size: 14.5px; color: var(--ink-2); line-height: 1.6; }
.tb-body strong { color: var(--ink); }

.tb-actions { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.tb-dots { display: flex; gap: 5px; }
.tb-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--line-strong); transition: all .18s; }
.tb-dot.is-on { background: var(--accent); width: 18px; border-radius: 3px; }
.tb-buttons { display: flex; gap: 8px; }
.tb-buttons .btn { padding: 8px 16px; font-size: 14px; }

.tb-close {
  position: absolute; top: 10px; right: 12px;
  width: 26px; height: 26px; border: 0; border-radius: 50%;
  background: transparent; color: var(--ink-3);
  font-size: 20px; line-height: 1; cursor: pointer;
}
.tb-close:hover { background: var(--surface-2); color: var(--ink); }

/* welcome / finish panel */
.tour-bubble.tour-welcome {
  top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: min(430px, calc(100vw - 32px));
  padding: 30px 30px 24px; text-align: center;
}
.tour-welcome .tw-mark {
  width: 54px; height: 54px; margin: 0 auto 14px;
  display: grid; place-items: center; border-radius: 50%;
  background: var(--accent-wash); color: var(--accent-deep);
}
.tour-welcome h2 { font-size: 25px; margin-bottom: 10px; }
.tour-welcome p { margin: 0 0 18px; font-size: 15px; color: var(--ink-2); line-height: 1.6; }
.tw-actions { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }
.tw-foot { margin: 16px 0 0 !important; font-size: 12.5px; color: var(--ink-3); }

@media (max-width: 620px) {
  .tour-bubble { padding: 18px; }
  .tour-bubble[data-arrow]::before { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .tour-overlay, .tour-bubble, .tour-spot { animation: none; transition: none; }
}

/* ===================== library: staff editing + sheets ================== */

.staff-bar {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  margin-bottom: 16px;
}

.edit-btn {
  width: 30px; height: 30px; flex: none; border-radius: var(--r-sm);
  border: 1px solid transparent; background: transparent; color: var(--ink-3);
  display: grid; place-items: center; cursor: pointer; transition: all .14s;
}
.edit-btn:hover { background: var(--accent-wash); border-color: var(--accent); color: var(--accent-deep); }
.doc .edit-btn { opacity: 0; }
.doc:hover .edit-btn, .doc .edit-btn:focus-visible { opacity: 1; }

/* whole-page drop hint */
body.page-drop::after {
  content: ""; position: fixed; inset: 10px; z-index: 700; pointer-events: none;
  border: 2px dashed var(--accent); border-radius: var(--r-lg);
  background: var(--accent-wash);
}

/* dialogs */
dialog.sheet {
  width: min(860px, calc(100vw - 32px));
  max-height: calc(100vh - 48px);
  padding: 0; border: 1px solid var(--line); border-radius: var(--r-lg);
  background: var(--surface); color: var(--ink);
  box-shadow: var(--shadow-lg); overflow: hidden;
}
dialog.sheet-narrow { width: min(440px, calc(100vw - 32px)); }
dialog.sheet::backdrop { background: rgba(12, 18, 20, .5); backdrop-filter: blur(2px); }
dialog.sheet[open] { animation: sheet-in .18s cubic-bezier(.2,.9,.3,1.2); }
@keyframes sheet-in { from { opacity: 0; transform: translateY(8px) scale(.99); } }

.sheet-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 18px 22px; border-bottom: 1px solid var(--line); background: var(--surface);
}
.sheet-head h2 { font-family: var(--serif); font-size: 20px; font-weight: 500; margin: 0; }
.sheet-close {
  width: 32px; height: 32px; border: 0; border-radius: 50%;
  background: transparent; color: var(--ink-3); font-size: 22px; line-height: 1; cursor: pointer;
}
.sheet-close:hover { background: var(--surface-2); color: var(--ink); }
.sheet-body {
  padding: 20px 22px; overflow-y: auto; overflow-x: hidden;
  max-height: calc(100vh - 190px);
}
.sheet-foot {
  display: flex; gap: 10px; padding: 16px 22px;
  border-top: 1px solid var(--line); background: var(--surface-2);
}

/* the uploader sits inside the sheet, so trim its outer spacing */
.sheet-body .dropzone { padding: 30px 20px; }
.sheet-body .group-card { margin-top: 16px; }
.sheet-body .targets { margin-bottom: 0; }
.upload-done { text-align: center; padding: 26px 10px; }
.upload-done p { font-size: 15.5px; margin: 0 0 16px; }
.upload-done .upload-actions { justify-content: center; margin-top: 0; }

/* the library's own drop area, in place of an "add" button */
.page-dropzone { margin-bottom: 18px; padding: 26px 20px; }
.page-dropzone .dz-title {
  font-family: var(--serif); font-size: 19px; font-weight: 500;
  color: var(--ink); margin: 2px 0 4px;
}
.page-dropzone svg { margin-bottom: 6px; }
.page-dropzone .dz-main { font-size: 15px; }

/* ===================== category colour + grouping ====================== */

/* chips pick up their category's colour */
.chip[style*="--cat"] { border-color: color-mix(in srgb, var(--cat) 34%, var(--line-strong)); }
.chip[style*="--cat"]:hover { border-color: var(--cat); color: var(--cat); }
.chip[style*="--cat"].is-on {
  background: var(--cat); border-color: var(--cat); color: #fff;
}
.tag.has-colour {
  background: color-mix(in srgb, var(--cat) 12%, transparent);
  border-color: color-mix(in srgb, var(--cat) 28%, transparent);
  color: color-mix(in srgb, var(--cat) 78%, var(--ink));
}
.folder[style*="--cat"] .folder-icon {
  background: color-mix(in srgb, var(--cat) 12%, transparent);
  color: color-mix(in srgb, var(--cat) 82%, var(--ink));
}
.folder[style*="--cat"][open] { border-color: color-mix(in srgb, var(--cat) 38%, var(--line)); }

/* view switcher */
.view-row { display: flex; align-items: center; gap: 12px; margin: 0 0 16px; flex-wrap: wrap; }
.view-label {
  font-size: 11.5px; letter-spacing: .09em; text-transform: uppercase;
  color: var(--ink-3); font-weight: 600;
}
.segmented {
  display: inline-flex; background: var(--surface-2);
  border: 1px solid var(--line); border-radius: 999px; padding: 3px;
}
.seg {
  padding: 6px 15px; border-radius: 999px; font-size: 13.5px; font-weight: 500;
  color: var(--ink-2); text-decoration: none; transition: all .14s;
}
.seg:hover { color: var(--accent-deep); }
.seg.is-on { background: var(--surface); color: var(--ink); box-shadow: var(--shadow-sm); }

/* section headings carry the category colour */
.year-label.has-colour {
  color: color-mix(in srgb, var(--cat) 80%, var(--ink));
  border-bottom-color: color-mix(in srgb, var(--cat) 30%, var(--line));
  font-family: var(--sans); font-size: 13px; letter-spacing: .06em;
  display: flex; align-items: center; gap: 9px;
}
.year-label.has-colour::before {
  content: ""; width: 9px; height: 9px; border-radius: 50%; background: var(--cat);
}
.year-count {
  margin-left: auto; font-family: var(--mono); font-size: 11px;
  color: var(--ink-3); letter-spacing: 0;
}

/* "show more" inside a section */
.more-block { margin-top: 2px; }
.more-toggle {
  list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 14px; margin-top: 6px;
  border: 1px solid var(--line-strong); border-radius: 999px;
  background: var(--surface); color: var(--ink-2);
  font-size: 13.5px; font-weight: 500; transition: all .14s;
}
.more-toggle::-webkit-details-marker { display: none; }
.more-toggle::after { content: "▾"; font-size: 11px; }
.more-toggle:hover { border-color: var(--accent); color: var(--accent-deep); }
.more-block[open] .more-toggle::after { content: "▴"; }
.more-body { display: grid; gap: 10px; margin-top: 10px; }

/* ---------- board ------------------------------------------------------- */

.board-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.board-tools { display: flex; gap: 8px; flex-wrap: wrap; }

.board-grid {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: 22px;
}
/* One card per member, all equal — nobody is featured. A photo takes the
   left third, whole and matted; without one, the text takes the full width.
   No placeholder of any kind stands in for a missing photograph. */
.member-card {
  display: grid; grid-template-columns: minmax(0, 1fr); gap: 30px;
  align-items: start;
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  border-radius: var(--r);
  padding: 26px 30px;
  box-shadow: var(--shadow-sm);
}
.member-card.has-photo { grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); }
.member-stage {
  display: flex; align-items: center; justify-content: center;
  aspect-ratio: 4 / 5;
  background: var(--panel); border: 1px solid var(--line);
}
.member-photo { max-width: 100%; max-height: 100%; display: block; }
.member-body { min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.member-name {
  font-family: var(--serif); font-size: 26px; font-weight: 500;
  letter-spacing: -.005em; margin: 0; line-height: 1.15;
}
.member-title {
  margin: 0; font-size: 11.5px; font-weight: 600;
  letter-spacing: .15em; text-transform: uppercase; color: var(--ink-3);
}
/* Collapsed, the bio stands roughly as tall as the portrait beside it and
   fades out; open, it runs free. The fade only exists while clamped. */
.member-bio {
  margin-top: 6px;
  max-height: 232px; overflow: hidden;
  -webkit-mask-image: linear-gradient(#000 62%, transparent);
  mask-image: linear-gradient(#000 62%, transparent);
}
.member-card.is-open .member-bio {
  max-height: none;
  -webkit-mask-image: none; mask-image: none;
}
.member-bio p { margin: 0 0 10px; font-size: 15px; line-height: 1.62; color: var(--ink-2); }
.member-bio p:last-child { margin-bottom: 0; }
.member-links { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; }
.bio-toggle {
  display: inline-flex; align-items: center; gap: 7px; min-height: 36px;
  padding: 0; background: none; border: 0; cursor: pointer;
  font: inherit; font-size: 13.5px; font-weight: 600; color: var(--accent);
}
.bio-toggle:hover { color: var(--accent-deep); }
.bio-toggle svg { transition: transform .15s; }
.member-card.is-open .bio-toggle svg { transform: rotate(180deg); }
.member-mailto {
  display: inline-flex; align-items: center; gap: 7px; min-height: 36px;
  font-size: 13.5px; font-weight: 600;
}
@media (max-width: 620px) {
  .member-card { padding: 20px; gap: 18px; }
  .member-card.has-photo { grid-template-columns: minmax(0, 1fr); }
  .member-stage { aspect-ratio: auto; height: 300px; }
}
.member-admin {
  display: flex; gap: 6px; margin-top: 8px;
}
.member-admin form { margin: 0; }

.bio-head { display: flex; gap: 16px; align-items: center; margin-bottom: 16px; }
.bio-head .member-title { margin: 0; }
.member-bio { font-size: 15px; color: var(--ink-2); line-height: 1.7; }
.member-bio p { margin: 0 0 11px; }
.member-bio p:last-child { margin-bottom: 0; }
.member-bio ul, .member-bio ol { margin: 0 0 11px; padding-left: 20px; }

/* removed list */
.removed-block { margin-top: 26px; }
.removed-list { list-style: none; margin: 12px 0 0; padding: 0; display: grid; gap: 8px; }
.removed-list li {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  background: var(--surface-2); border: 1px dashed var(--line-strong);
  border-radius: var(--r); padding: 11px 15px;
}
.removed-list form { margin: 0 0 0 auto; }
.rm-name { font-weight: 600; }

/* reorder */
.reorder-list { list-style: none; margin: 14px 0 0; padding: 0; display: grid; gap: 7px; }
.reorder-row {
  display: flex; align-items: center; gap: 12px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r); padding: 9px 13px; cursor: grab;
  transition: border-color .14s, box-shadow .14s, opacity .14s;
}
.reorder-row:hover { border-color: var(--accent); box-shadow: var(--shadow-sm); }
.reorder-row.is-held { opacity: .45; border-style: dashed; }
.grip { color: var(--ink-3); flex: none; }
.rm-thumb {
  width: 34px; height: 34px; flex: none; border-radius: 50%;
  object-fit: cover; background: var(--surface-2); font-size: 15px;
}

/* small rich-text editor */
.editor { border: 1px solid var(--line-strong); border-radius: var(--r-sm); overflow: hidden; }
.editor-bar {
  display: flex; gap: 2px; padding: 6px; background: var(--surface-2);
  border-bottom: 1px solid var(--line);
}
.editor-bar button {
  width: 30px; height: 28px; border: 0; border-radius: 5px;
  background: transparent; color: var(--ink-2); cursor: pointer; font-size: 14px;
}
.editor-bar button:hover { background: var(--surface); color: var(--accent-deep); }
.editor-area {
  min-height: 150px; max-height: 320px; overflow-y: auto;
  padding: 12px 14px; font-size: 14.5px; line-height: 1.65; background: var(--surface);
}
.editor-area:focus { outline: none; box-shadow: inset 0 0 0 2px var(--accent-wash); }
.editor-area p { margin: 0 0 9px; }
.editor-area ul, .editor-area ol { margin: 0 0 9px; padding-left: 20px; }

/* library controls, above the search box */
.controls {
  display: grid; gap: 10px; margin-bottom: 16px;
  padding-bottom: 14px; border-bottom: 1px solid var(--line);
}
.control-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.control-row .view-label { min-width: 66px; }


/* ---------- date fields ------------------------------------------------- */

/* The native control is fine underneath; it just needs to match everything
   else. Left as a native input on purpose — the platform picker is better on
   a phone than anything hand-rolled, and it is keyboard-accessible already. */
input[type="date"] {
  appearance: none; -webkit-appearance: none;
  font-family: var(--sans); font-variant-numeric: tabular-nums;
  line-height: 1.2; min-height: 44px; max-width: 100%;
}
input[type="date"]::-webkit-datetime-edit { padding: 0; }
input[type="date"]::-webkit-datetime-edit-fields-wrapper { padding: 0; }
input[type="date"]::-webkit-inner-spin-button,
input[type="date"]::-webkit-clear-button { display: none; }
input[type="date"]::-webkit-calendar-picker-indicator {
  margin-left: auto; padding: 4px; border-radius: 5px; cursor: pointer;
  opacity: .55; transition: opacity .14s, background .14s;
  /* Tinted to the theme rather than the browser's default black glyph. */
  filter: grayscale(1);
}
input[type="date"]::-webkit-calendar-picker-indicator:hover {
  opacity: 1; background: var(--accent-wash);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) input[type="date"]::-webkit-calendar-picker-indicator {
    filter: grayscale(1) invert(1);
  }
}

/* the edit sheet's own fields */
.sheet-narrow .stack { gap: 16px; }
.sheet-narrow .field label { margin-bottom: 2px; }
.sheet-narrow .field input,
.sheet-narrow .field select { width: 100%; box-sizing: border-box; }
.sheet-narrow .checkline {
  align-items: flex-start; gap: 9px; line-height: 1.45;
  white-space: normal; padding-top: 2px;
}
.sheet-narrow .checkline input { margin-top: 3px; flex: none; }
.danger-btn:hover { border-color: var(--bad); color: var(--bad); background: var(--bad-wash); }
.edit-btn.danger-hover:hover {
  background: var(--bad-wash); border-color: var(--bad); color: var(--bad);
}
.inline-form { margin: 0; display: inline-flex; }

/* trash page */
.trash-list { list-style: none; margin: 12px 0 0; padding: 0; display: grid; gap: 8px; }
.trash-list li {
  display: flex; align-items: center; gap: 14px;
  background: var(--surface-2); border: 1px dashed var(--line-strong);
  border-radius: var(--r); padding: 12px 16px;
}
.trash-list form { margin: 0 0 0 auto; }
.trash-main { min-width: 0; display: grid; gap: 1px; }
.trash-title { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.trash-meta { font-size: 12.5px; color: var(--ink-3); }


/* The native select arrow sits flush against the edge and ignores the theme;
   draw our own with room around it instead. */
select {
  appearance: none; -webkit-appearance: none;
  padding-right: 40px;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%235d6a72' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 13px center;
  background-size: 16px;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) select {
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23aab8bc' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  }
}
select::-ms-expand { display: none; }

/* trash button on a row shares the edit button's shape, not its behaviour */
.row-btn {
  width: 30px; height: 30px; flex: none; border-radius: var(--r-sm);
  border: 1px solid transparent; background: transparent; color: var(--ink-3);
  display: grid; place-items: center; cursor: pointer; transition: all .14s;
}
.doc .row-btn { opacity: 0; }
.doc:hover .row-btn, .doc .row-btn:focus-visible { opacity: 1; }
.row-btn.danger-hover:hover {
  background: var(--bad-wash); border-color: var(--bad); color: var(--bad);
}


/* ---------- shared confirmation ---------------------------------------- */

dialog.confirm-sheet { width: min(430px, calc(100vw - 32px)); }
.confirm-sheet .sheet-body { padding: 28px 28px 22px; text-align: center; }
.confirm-mark {
  width: 48px; height: 48px; margin: 0 auto 14px;
  display: grid; place-items: center; border-radius: 50%;
  background: var(--bad-wash); color: var(--bad);
}
.confirm-sheet h2 {
  font-family: var(--serif); font-size: 21px; font-weight: 500; margin: 0 0 8px;
}
.confirm-sheet p { margin: 0; color: var(--ink-2); font-size: 14.5px; line-height: 1.6; }
.confirm-foot { justify-content: center; }
.btn.confirm-go.is-danger { background: var(--bad); border-color: var(--bad); }
.btn.confirm-go.is-danger:hover {
  background: color-mix(in srgb, var(--bad) 82%, black); border-color: transparent;
}

.field-note {
  margin: 0; font-size: 13px; color: var(--ink-3); line-height: 1.55;
  padding: 10px 12px; background: var(--surface-2);
  border: 1px solid var(--line); border-radius: var(--r-sm);
}


/* ---- owners: filter chips and the deleted view ---- */
.chip-n {
  margin-left: 7px; font-size: 12px; font-variant-numeric: tabular-nums;
  opacity: .62;
}
.chip.is-on .chip-n { opacity: .8; }
.chip-quiet:not(.is-on) { opacity: .72; }
.view-note {
  margin: 0 0 14px; padding: 11px 14px;
  border: 1px dashed var(--line-strong); border-radius: var(--r);
  color: var(--ink-2); font-size: 14px; line-height: 1.5;
}
tr.is-off .person-name { text-decoration: line-through; text-decoration-thickness: 1px; }

/* ---- account menu in the header ---- */
.usermenu { position: relative; margin-left: 4px; }
.usermenu > summary { list-style: none; cursor: pointer; }
.usermenu > summary::-webkit-details-marker { display: none; }
.avatar-btn {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 6px 3px 3px; border-radius: 999px;
  border: 1px solid transparent; transition: background .15s, border-color .15s;
}
.avatar-btn:hover { background: rgba(255, 255, 255, .1); border-color: rgba(255, 255, 255, .16); }
.usermenu[open] .avatar-btn { background: rgba(255, 255, 255, .13); border-color: rgba(255, 255, 255, .2); }
.avatar {
  display: grid; place-items: center;
  width: 32px; height: 32px; border-radius: 50%;
  /* Drawn in white alpha rather than the accent: the accent has to work on
     paper for links and buttons, and three properties' worth of it cannot all
     be trusted to stay legible against their own masthead. */
  background: rgba(255, 255, 255, .16); color: #fff;
  border: 1px solid rgba(255, 255, 255, .1);
  font-size: 12.5px; font-weight: 600; letter-spacing: .3px;
  text-transform: uppercase; font-family: var(--sans, inherit);
}
.avatar-chev { color: rgba(255, 255, 255, .6); transition: transform .15s; }
.usermenu[open] .avatar-chev { transform: rotate(180deg); }

.usermenu-panel {
  position: absolute; right: 0; top: calc(100% + 8px); z-index: 60;
  min-width: 236px; padding: 6px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r); box-shadow: var(--shadow-lg, var(--shadow));
  animation: menu-in .14s ease;
}
@keyframes menu-in { from { opacity: 0; transform: translateY(-4px); } }
.usermenu-who {
  display: grid; gap: 2px; padding: 9px 11px 11px;
  border-bottom: 1px solid var(--line); margin-bottom: 5px;
}
.usermenu-name { font-weight: 600; font-size: 14px; }
.usermenu-mail { font-size: 12.5px; color: var(--ink-3); word-break: break-all; }
.usermenu-panel a,
.usermenu-panel button {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 9px 11px; border: 0; border-radius: 8px;
  background: none; color: var(--ink); font: inherit; font-size: 14px;
  text-align: left; text-decoration: none; cursor: pointer;
}
.usermenu-panel a:hover,
.usermenu-panel button:hover { background: var(--surface-2); }
.usermenu-panel a svg, .usermenu-panel button svg { color: var(--ink-3); flex: none; }
.usermenu-panel form { margin: 0; }

/* ---- profile / password pages ---- */
.account-layout {
  display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
  gap: 22px; align-items: start;
}
@media (max-width: 780px) { .account-layout { grid-template-columns: 1fr; } }
.card-form {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r); padding: 22px; box-shadow: var(--shadow-sm);
}
.card-form.narrow { max-width: 520px; }
.card-form .field + .field { margin-top: 16px; }
.form-foot {
  display: flex; align-items: center; gap: 10px;
  margin-top: 20px; padding-top: 18px; border-top: 1px solid var(--line);
}
.form-error { margin: 6px 0 0; color: var(--bad); font-size: 13.5px; }
.account-side {
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: var(--r); padding: 20px;
}
.side-title { margin: 0 0 12px; font-size: 15px; }
.side-list { margin: 0 0 14px; display: grid; gap: 3px; }
.side-list dt { font-size: 12px; text-transform: uppercase; letter-spacing: .05em; color: var(--ink-3); }
.side-list dd { margin: 0 0 10px; font-size: 14px; word-break: break-word; }


/* ---------- the cabinet: a standing rail beside the documents -------------
   The rail is the point of this layout, so on a wide screen it never leaves.
   Below 900px there is no room for it and it becomes a drawer — see the
   media query at the end of this block. */
.cabinet {
  /* --edge: where the masthead's own content begins (its .wrap is 1020px,
     padded 20). On wide screens the rail swallows the negative space to the
     window edge, and its inner padding pushes the labels to --edge, so the
     rail text lines up with the logo above it. */
  --edge: max(20px, calc((100vw - 1020px) / 2 + 20px));
  display: grid; grid-template-columns: calc(var(--edge) + 244px) minmax(0, 1fr); gap: 0;
  align-items: start;
}
.wrap.full-bleed { max-width: none; padding: 0; }
main.wrap.full-bleed { padding-top: 0; padding-bottom: 0; }

/* Two parts on purpose. The COLUMN runs the full height of the page so the
   panel never stops halfway down a long list; the PANEL inside it is what
   sticks under the masthead and carries the texture, so the texture always
   fills exactly the part you can see rather than stretching over the whole
   document. */
.rail {
  align-self: stretch;
  min-height: calc(100vh - var(--header-h));
  background: var(--panel);
  border-right: 1px solid var(--line);
}
.rail-inner {
  display: flex; flex-direction: column; gap: 24px;
  position: sticky; top: var(--header-h);
  height: calc(100vh - var(--header-h));
  /* Labels carry 12px of their own padding; --edge minus that lines the
     text up with the logo. */
  padding: 26px 16px 30px calc(var(--edge, 16px) - 12px);
  overflow-y: auto;
  /* A watermark of the property: the real photograph, greyscale and unblurred
     so it is recognisable, but with its tones squeezed into 220–255 before it
     ever reaches the browser. Multiplied against the panel it can therefore
     darken the paper by at most about a seventh — measured so the faintest
     label still clears 4.5:1 over the darkest part of the picture. Blending
     against the COLOUR means one greyscale file tints itself correctly for
     all three properties. */
  background-color: var(--panel);
  background-image: var(--rail-image, none);
  /* Either one photograph covering the panel, or a small tile repeated —
     the resorts use both conventions. Same tonal band either way, so the
     contrast guarantee does not depend on which. */
  background-size: var(--rail-size, cover);
  background-repeat: var(--rail-repeat, no-repeat);
  background-position: center top;
  background-blend-mode: multiply;
}
.rail-head { display: none; }
.rail-group { display: flex; flex-direction: column; gap: 2px; }
.rail-label {
  margin: 0 0 8px; padding: 0 12px;
  font-size: 10.5px; font-weight: 600; letter-spacing: .16em;
  text-transform: uppercase; color: var(--ink-2);
}
.rail-item {
  display: flex; align-items: center; gap: 10px;
  min-height: 42px; padding: 0 12px; border-radius: var(--r-sm);
  /* --ink-2, not --ink-3: the panel is a step darker than the page, which
     eats exactly the headroom --ink-3 had left. */
  color: var(--ink-2); text-decoration: none;
  font-size: 14.5px; line-height: 1.3;
  transition: background .15s, color .15s, box-shadow .15s;
}
.rail-item:hover { background: rgba(255, 255, 255, .55); color: var(--ink); }
.rail-item.is-on {
  background: var(--surface); color: var(--ink); font-weight: 600;
  box-shadow: var(--shadow-sm);
}
.rail-dot {
  width: 8px; height: 8px; flex: none; border-radius: 50%;
  background: var(--cat, var(--ink-3));
}
.rail-n {
  margin-left: auto; font-size: 12.5px; color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.rail-item.is-on .rail-n { color: var(--ink); }
.rail-group + .rail-group {
  padding-top: 20px; border-top: 1px solid var(--line-strong);
}


.pane { min-width: 0; max-width: 1080px; padding: 34px 40px 64px; }
.pane-head {
  display: flex; flex-wrap: wrap; align-items: flex-end;
  justify-content: space-between; gap: 18px 24px; margin-bottom: 22px;
}
.pane-title { min-width: 0; }
.pane-tools { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.pane-tools .search-field { flex: 1 1 240px; }
.pane-tools .search-field input { padding-right: 38px; }

.rail-open { display: none; }
.rail-scrim { display: none; }

@media (max-width: 900px) {
  .cabinet { grid-template-columns: minmax(0, 1fr); }
  .pane { padding: 28px 20px 56px; max-width: none; }

  /* Not a button: a full-width strip in the panel's own shade, bleeding to
     the screen edges, with a chevron saying "this pulls out from the side".
     It previews the drawer it opens. */
  .rail-open {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    width: 100%; margin: 0;
    min-height: 52px; padding: 0 20px;
    background: var(--panel); color: var(--ink);
    border: 0; border-bottom: 1px solid var(--line);
    font: inherit; font-size: 14.5px; font-weight: 600; cursor: pointer;
  }
  .rail-open svg { color: var(--ink-2); flex: none; }
  .rail {
    position: fixed; inset: 0 auto 0 0; z-index: 60;
    width: min(306px, 84vw); min-height: 0;
    border-right: 1px solid var(--line-strong);
    box-shadow: 0 0 60px rgba(20, 24, 26, .3);
    transform: translateX(-101%); transition: transform .22s ease;
  }
  .rail-inner {
    position: static; height: 100%;
    padding: 20px 14px; overflow-y: auto;
  }
  .rail.is-open { transform: none; }
  .rail-head {
    display: flex; align-items: center; justify-content: space-between;
    margin-bottom: 4px;
  }
  .rail-title { font-family: var(--serif); font-size: 20px; font-weight: 500; color: var(--ink); }
  .rail-close {
    display: grid; place-items: center; width: 44px; height: 44px;
    margin-right: -10px; border: 0; border-radius: var(--r-sm);
    background: none; color: var(--ink-2); cursor: pointer;
  }
  .rail-item { min-height: 46px; font-size: 15px; }
  .rail-scrim {
    display: block; position: fixed; inset: 0; z-index: 55;
    background: rgba(20, 24, 26, .46);
  }
  .pane-head { align-items: stretch; flex-direction: column; }
  .pane-tools .search-field { flex: 1 1 100%; }
}
@media (prefers-reduced-motion: reduce) { .rail { transition: none; } }


/* One-line masthead on a phone: hamburger, logo, account. The nav drops
   out of the flow into a panel under the bar. */
@media (max-width: 620px) {
  .header-inner { flex-wrap: nowrap; gap: 8px; }
  .nav-burger {
    display: grid; place-items: center; flex: none;
    width: 44px; height: 44px; margin-left: -10px;
    background: none; border: 0; border-radius: var(--r-sm);
    color: rgba(255, 255, 255, .85); cursor: pointer;
  }
  .nav-burger[aria-expanded="true"] { background: rgba(255, 255, 255, .12); color: #fff; }
  .brand { flex: 1; justify-content: center; min-width: 0; }
  .site-nav {
    display: none;
    position: absolute; top: 100%; left: 0; right: 0; z-index: 30;
    flex-direction: column; align-items: stretch; gap: 0;
    padding: 6px 14px 14px;
    background: var(--masthead);
    border-bottom: 3px solid var(--vivid);
    box-shadow: 0 18px 34px -18px rgba(0, 0, 0, .5);
  }
  .site-nav.is-open { display: flex; }
  .site-nav a {
    display: flex; align-items: center; min-height: 48px;
    font-size: 12.5px; padding: 0 12px;
  }
  .nav-divider { width: auto; height: 1px; margin: 6px 12px; }
}
@media (max-width: 520px) {
  .doc { gap: 12px; padding: 14px; }
  .folder-head { gap: 10px; padding: 13px 14px; }
  .page-dropzone { padding: 20px 16px; }
}


/* ---- the generated-password dialog ---- */
.pw-big {
  display: block; padding: 14px 16px; text-align: center;
  font-size: 19px; letter-spacing: .04em;
  background: var(--surface-2); border: 1px dashed var(--line-strong);
  border-radius: var(--r-sm); user-select: all;
}

/* ---- Owners on a phone: the table becomes cards ---- */
@media (max-width: 760px) {
  .people-table thead { display: none; }
  .people-table, .people-table tbody { display: block; }
  .people-table tr {
    display: grid; gap: 4px; padding: 14px 16px;
    border-bottom: 1px solid var(--line);
  }
  .people-table tr:last-child { border-bottom: 0; }
  .people-table td { display: block; padding: 0; border: 0; min-width: 0; }
  .people-table td.num::before { content: "Last signed in: "; color: var(--ink-3); }
  .row-actions { justify-content: flex-start; margin-top: 8px; }
}

/* ---- the board portrait matte carries the property's texture, exactly as
        the library's browse panel does ---- */
.member-stage {
  background-color: var(--panel);
  background-image: var(--rail-image, none);
  background-size: var(--rail-size, cover);
  background-repeat: var(--rail-repeat, no-repeat);
  background-position: center top;
  background-blend-mode: multiply;
}

/* ---- the sign-in scene ------------------------------------------------ */
main.wrap.login-page {
  max-width: none; padding: 0;
  min-height: 100vh; display: grid; place-items: center;
  /* The opening hold: the logo alone on solid colour, fading softly up, before
     anything else moves. Every other beat is expressed relative to it, so
     changing the hold moves the whole entrance together. */
  --hold: .5s;
}
.login-scene { position: fixed; inset: 0; z-index: 0; overflow: hidden; background: var(--masthead); }
/* Exactly two layers. `is-front` = the photograph on show; `is-arriving` =
   the one sweeping in over it. They are never both set on one layer, so no
   class combination can cancel the animation.

   The z-indexes are load-bearing, not tidying. The two layers swap roles every
   cycle, so without them stacking fell to DOM order and the FIRST layer always
   painted underneath the second: every second transition swept perfectly but
   did it hidden behind the opaque outgoing photograph, and all you saw was the
   old one blinking off at the end. Hence "nice, jolt, nice, jolt". The
   arriving layer must be above the one it is replacing whichever way round
   they currently are. */
.login-layer { position: absolute; inset: 0; opacity: 0; }
.login-layer.is-front { opacity: 1; z-index: 1; }
.login-layer.is-arriving {
  opacity: 1; z-index: 2;
  -webkit-mask-image: linear-gradient(105deg, #000 55%, transparent 78%);
  mask-image: linear-gradient(105deg, #000 55%, transparent 78%);
  -webkit-mask-size: 300% 100%; mask-size: 300% 100%;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  animation: login-sweep 3.6s cubic-bezier(.33, .1, .2, 1) both;
}
/* The photograph drifts on its own layer, forever and independently, so no
   transition can ever interrupt or restart the movement. */
.login-drift {
  position: absolute; inset: -6%;
  background-size: cover; background-position: center;
  animation: login-drift 28s ease-in-out infinite alternate;
}
.login-layer:nth-child(2) .login-drift { animation-delay: -14s; }
@keyframes login-drift {
  from { transform: translate3d(-1.4%, -0.5%, 0) scale(1.08); }
  to   { transform: translate3d(1.4%, 0.5%, 0) scale(1.12); }
}
/* The start must be COMPLETELY hidden, which 100% is not. At mask-size 300%
   and position 100% the viewport maps onto 66.7-100% of the gradient, and the
   gradient only becomes fully transparent at 78% — so the leftmost third of
   the screen showed a band of the incoming photograph before the sweep had
   begun. Invisible at the old 200ms delay; obvious once the entrance holds on
   the logo for a second. 120% puts the viewport past 78% (and, with
   `no-repeat`, partly outside the mask, which is transparent too). */
@keyframes login-sweep {
  from { -webkit-mask-position: 120% 0; mask-position: 120% 0; }
  to   { -webkit-mask-position: 0% 0;   mask-position: 0% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .login-layer.is-arriving { animation: none; mask-image: none; -webkit-mask-image: none; }
  .login-drift { animation: none; }
}
.login-scrim {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(10, 14, 15, .30), rgba(10, 14, 15, .52));
}

.login-card {
  position: relative; z-index: 1;
  width: min(420px, calc(100vw - 40px));
  margin: 48px 0;
  border-radius: var(--r-lg); overflow: hidden;
  /* Deliberately NO background of its own. During the hold the card is only as
     tall as its brand block, so a white card behind a brand block that has not
     faded in yet IS a white box sitting on the ground before anything has
     happened — you watched the logo fade into it. The white belongs to the
     form, which is the part that opens. The shadow joins at the same moment,
     for the same reason. */
  box-shadow: 0 12px 28px rgba(8, 12, 13, .30), 0 44px 90px -30px rgba(8, 12, 13, .55);
  /* Beat two: the panel opens. Animating the grid row (not a scale) means the
     form genuinely unfolds instead of being squashed, and because the card is
     only as tall as its brand block to begin with, there is no empty white box
     on screen first. */
  display: grid; grid-template-rows: auto 1fr;
  animation: login-open .5s cubic-bezier(.2, .74, .28, 1) calc(var(--hold) + .18s) both;
}
/* Beat one: the logo, alone. The brand block is already `--masthead`, the same
   colour as the scene's ground, so before the photograph arrives this reads as
   a mark on solid colour rather than a panel. */
.login-brand { animation: login-mark-in var(--hold) ease-in-out both; }
.login-body { overflow: hidden; min-height: 0; background: var(--surface); }
@keyframes login-mark-in {
  from { opacity: 0; transform: translateY(5px); }
  to   { opacity: 1; transform: none; }
}
@keyframes login-open {
  from {
    grid-template-rows: auto 0fr;
    box-shadow: 0 0 0 rgba(8, 12, 13, 0), 0 0 0 rgba(8, 12, 13, 0);
  }
  to {
    grid-template-rows: auto 1fr;
    box-shadow: 0 12px 28px rgba(8, 12, 13, .30), 0 44px 90px -30px rgba(8, 12, 13, .55);
  }
}
/* Beat three: the opening photograph, swept in quicker than the rotation. */
.login-layer.is-arriving.is-intro { animation-duration: .8s; animation-delay: calc(var(--hold) + .2s); }

/* The sweep, felt on the card. This is NOT a shine timed to look like the
   wavefront — it IS the wavefront, seen through the logo block. The highlight
   is positioned against the VIEWPORT (`background-attachment: fixed`) at the
   same angle, size and start position as the sweep's mask, and the JS hands it
   the same duration and delay as the sweep it just started. So the light
   crosses the logo at the exact moment the photograph's edge crosses that part
   of the screen, at any window size, with no numbers to keep in step. Where
   `fixed` is unsupported it falls back to sweeping the block on its own — a
   shine either way, just not aligned. */
.login-brand::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background-image: linear-gradient(105deg,
    transparent 52%, rgba(255, 255, 255, .11) 66%, transparent 80%);
  background-size: 300% 100%;
  background-attachment: fixed;
  background-position: 120% 0;
}
.is-sweeping .login-brand::after {
  animation: login-shine var(--shine-dur, 3.6s) cubic-bezier(.33, .1, .2, 1)
             var(--shine-delay, 0ms) both;
}
@keyframes login-shine {
  from { background-position: 120% 0; }
  to   { background-position: 0% 0; }
}
/* Seen it already this session: land on the finished state with no beats.
   After the three rules above, for the same cascade reason as below. */
.no-entrance .login-brand { animation: none; }
.no-entrance .login-card { animation: none; grid-template-rows: auto 1fr; }

/* Must come AFTER the three beats above: same specificity, so the last rule
   wins and an override written earlier would never apply. */
@media (prefers-reduced-motion: reduce) {
  .login-card { animation: none; grid-template-rows: auto 1fr; }
  .login-brand { animation: none; }
  .is-sweeping .login-brand::after { animation: none; }
}
/* The brand band: the masthead, moved inside the card — the white-only logos
   need the dark field wherever they appear. */
.login-brand {
  position: relative;
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  padding: 30px 24px 26px;
  background: var(--masthead);
  border-bottom: 3px solid var(--vivid);
}
.login-mark { display: block; height: calc(var(--logo-h, 40px) * 1.15); max-width: 82%; width: auto; opacity: .96; }
.login-word { font-family: var(--serif); font-size: 24px; font-weight: 500; color: #fff; }
.login-sub {
  font-size: 10.5px; font-weight: 600; letter-spacing: .2em;
  text-transform: uppercase; color: rgba(255, 255, 255, .6);
}
.login-body-inner { padding: 26px 28px 24px; }
.login-body-inner .btn { width: 100%; justify-content: center; margin-top: 4px; }

/* ---- the staff-only marker -------------------------------------------
   One recognisable chip on every surface owners never see. The walkthrough
   explains it once; the chip keeps saying it afterwards. */
.staff-flag {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 9px; border-radius: 999px;
  background: var(--accent-wash);
  border: 1px solid color-mix(in srgb, var(--accent) 32%, transparent);
  color: var(--accent-deep);
  font-size: 9.5px; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; white-space: nowrap;
}
.page-dropzone { position: relative; }
.page-dropzone .staff-flag { position: absolute; top: 10px; right: 12px; }
.nav-staff {
  font-size: 9px; font-weight: 700; letter-spacing: .16em;
  text-transform: uppercase; color: rgba(255, 255, 255, .42);
  padding: 0 2px 0 4px;
}

/* ---- the sign-in photograph manager (unlisted staff page) ---- */
.scene-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 16px;
}
.scene-item {
  position: relative;
  margin: 0; background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r); overflow: hidden; box-shadow: var(--shadow-sm);
}
/* An opener is one of the photographs allowed to appear FIRST, so it earns a
   visible mark on the card, not just a pressed-looking button. */
.scene-item.is-starter { border-color: var(--vivid); box-shadow: 0 0 0 1px var(--vivid); }
.scene-badge {
  position: absolute; top: 8px; left: 8px;
  background: var(--vivid); color: #fff;
  font-size: 10.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
  padding: 3px 7px; border-radius: 999px;
}
.scene-actions { display: flex; align-items: center; justify-content: flex-end; gap: 6px; }
.scene-actions .mini.is-on { border-color: var(--vivid); color: var(--vivid); font-weight: 650; }
.scene-item img { display: block; width: 100%; aspect-ratio: 3 / 2; object-fit: cover; }
/* Name on its own line: with the Opener control added, a single row squeezed
   every filename down to an identical "sands-…" and you could not tell one
   card from another. */
.scene-item figcaption {
  display: flex; flex-direction: column; align-items: stretch; gap: 8px;
  padding: 10px 12px;
}
.scene-name {
  font-size: 12.5px; color: var(--ink-2); overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}
