/* ============================================================
   ONE OE Toolshed — page shell (server and prototype)
   Sits on top of the Object Edge design system (Product layer).
   Tokens only: no colour or size literals. Sizes read a system token
   (`--row`, `--prose-unit`, …) or a `--ts-*` property below; only the
   media query conditions keep their pixel values, since CSS cannot
   read a custom property there. Prototype-only rules live in
   assets/toolshed/prototype.css, which production does not serve.
   ============================================================ */

/* ——— Toolshed tokens (story 12.1; values from DESIGN.md `spacing.ts-*`) ———
   Two page widths only. The page, the top bar and the footer read `--ts-page` and `--ts-pad-x`,
   so the wordmark, crumbs, h1 and footer text share one edge on either width.
   Breakpoints (three): ≤ 900 two-column galleries; ≤ 640 the phone gutter, the avatar-only
   account menu, one-column galleries and cards, wrapping manage tabs; ≤ 480 the phone h1 and
   the pictures-only week grid. */
.oe-product {
  --ts-page-max: 1120px;        /* standard: galleries, tables, home, manage pages */
  --ts-page-narrow: 880px;      /* narrow: reading pages, sign-in, errors */
  --ts-gutter-x: 32px;          /* page, bar and footer side padding */
  --ts-gutter-x-phone: 16px;    /* at 640px and below */
  --ts-dot: 6px;                /* the eyebrow dot's size (.oec-eyebrow__dot), reused by the crumb dot */
  --ts-page-top: 48px;
  --ts-page-bottom: 72px;
  --ts-page-top-phone: 32px;
  --ts-page-bottom-phone: 56px;
  --ts-crumbs-gap: var(--row);
  --ts-head-gap: 48px;
  --ts-head-gap-phone: 36px;
  --ts-section-gap: 56px;
  --ts-headtext-max: 640px;
  --ts-card-min: 300px;
  --ts-grid-gap: 24px;
  --ts-measure: 720px;          /* one measure: the add form's typed text, moment text, list rows */
  /* Story 12.5 (fix 21): the literals DESIGN.md "Layout & Spacing" lists, as tokens. */
  --ts-hairline: 1px;           /* every rule and control border drawn locally */
  --ts-photo-band: var(--ink);  /* the year card's reaction band (story 20.3): solid ink where color-mix is unsupported … */
  --ts-label-offset: calc(var(--fs-app-label-md) * 1.4 + 7px); /* a field's label and its gap to the input (measured in Chrome): a button beside a field drops by this to meet its input (story 34.1) */
  --ts-w-bold: 700;             /* the moment page head (story 43.1); the system's own tokens stop at --w-semi 600 */
  --ts-tab-rule: 2px;           /* the rule over each manage tab (story 19.1), the design system tab underline's weight */
  --ts-bar-pad-y: 14px;         /* top bar and footer */
  --ts-bar-pad-y-phone: 12px;
  --ts-lh-head: 1.08;           /* the page h1 */
  --ts-tr-year: 0.02em;         /* the mono year on a year card */
  --ts-tr-brand: 0.02em;        /* the wordmark's alt text, if the image does not load */
  --ts-cat-max: 50%;            /* a gallery item's category: a long one truncates here, the name gives way first */
  --ts-vh-size: 1px;            /* the visually-hidden box; never tied to the hairline */
  --ts-card-min-h: 200px;       /* link cards */
  --ts-thumb: 64px;             /* Approvals and Removals thumbnails */
  --ts-photo-filter: saturate(0.75) sepia(0.12);   /* the one warm look on every photo (AD-2) */
  --ts-photo-max-h: 72vh;       /* the moment page photo */
  --ts-focus-width: 2px;        /* the ink outline of the focus ring */
  --ts-focus-halo: 4px;         /* the amber halo around it */
  --ts-focus-halo-wide: 6px;    /* gallery items, whose outline sits further out */
  --ts-notice-rule: 2px;        /* the notice's left rule */
  --ts-login-max: 460px;        /* the sign-in panel */
  --ts-textarea-min-h: 160px;   /* the add form's description */
  --ts-table-min: 640px;        /* tables scroll inside their wrapper below this */
  --ts-table-min-thumb: 740px;  /* … and below this with the picture column */
  /* The light tile under Google's mark on the ink sign-in button (story 12.3 review). */
  --ts-google-tile: var(--paper);
  --ts-google-tile-radius: 0;   /* square, as every system surface */
  --ts-google-tile-pad: calc(var(--prose-unit) / 2);
  /* The current page's width and gutter; the layout sets data-width="narrow" on narrow pages. */
  --ts-page: var(--ts-page-max);
  --ts-pad-x: var(--ts-gutter-x);
}
.oe-product[data-width="narrow"] { --ts-page: var(--ts-page-narrow); }

* { box-sizing: border-box; }

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--paper);
  color: var(--fg-1);
  font-family: var(--font-sans);
  font-size: var(--fs-app-text-md);
  line-height: 1.5;
}

a { color: inherit; }

/* ——— The focus ring (DESIGN.md components.focus-ring): ink outline, amber halo. One rule for the
   local controls; system components draw their own. A control may move the ring out by setting
   --ts-focus-offset and --ts-focus-spread (gallery items do). ——— */
.shell__footlink:focus-visible,
.shell__acctbtn:focus-visible,
.addphoto__drop:focus-visible,
.editframe:focus-visible,
.mitem:focus-visible {
  outline: var(--ts-focus-width) solid var(--ink);
  outline-offset: var(--ts-focus-offset, var(--ts-focus-width));
  box-shadow: 0 0 0 var(--ts-focus-spread, var(--ts-focus-halo)) var(--amber);
}

/* ——— Chrome bands ——— */
.shell__bar,
.shell__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(var(--prose-unit) * 2);
  /* Hairlines run the full window width; the contents sit in the page's container and gutter. */
  padding: var(--ts-bar-pad-y) max(var(--ts-pad-x), calc((100% - var(--ts-page)) / 2 + var(--ts-pad-x)));
}
.shell__bar { border-bottom: var(--ts-hairline) solid var(--rule); }
/* While an engagement team member views as an employee (story 21.1): a tinted band under the top
   bar, its text and "Back to admin view" in the page's container, as the bar's contents. */
.shell__viewas {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--prose-unit) calc(var(--prose-unit) * 2);
  padding: var(--prose-unit) max(var(--ts-pad-x), calc((100% - var(--ts-page)) / 2 + var(--ts-pad-x)));
  background: var(--paper-2);
  border-bottom: var(--ts-hairline) solid var(--rule);
}
.shell__viewastext { margin: 0; font-size: var(--fs-app-text-sm); color: var(--fg-1); }
.shell__viewas form { margin: 0; }
/* The label is short and fixed; the design system's 26ch button cap would cut it with the button's tracking. */
.shell__viewas .oec-btn { max-width: none; }
.shell__foot { border-top: var(--ts-hairline) solid var(--rule); margin-top: auto; }
/* The company link in the footer (story 10.1): mono label look, external mark after the text. */
.shell__footlink { display: inline-flex; align-items: center; gap: calc(var(--prose-unit) * 0.5); text-decoration: none; text-transform: none; }
.shell__footlink .oec-icon { width: var(--icon-xs); height: var(--icon-xs); }
.shell__footlink:hover { color: var(--ink); text-decoration: underline; text-underline-offset: calc(var(--prose-unit) * 0.375); }
.shell__right { display: inline-flex; align-items: center; gap: calc(var(--prose-unit) * 2.5); }

/* ——— Account menu (story 6.1): the design system's Menu with an Avatar trigger ——— */
.shell__acctbtn { padding: 0 0 0 calc(var(--prose-unit) * 0.5); gap: calc(var(--prose-unit) * 1.25); color: var(--fg-1); }
/* The Avatar is the containing block for the picture: keep `position: relative`, or the picture escapes the round Avatar's clip (story 7.4). */
.shell__avatar { position: relative; }
.shell__acctimg { position: absolute; inset: 0; }
.shell__acctopt {
  width: 100%;
  margin: 0;
  border: 0;
  background: none;
  text-align: left;
  text-decoration: none;
}
.shell__acctopt:focus { outline: none; }
.shell__acctopt:focus-visible { outline: var(--ts-focus-width) solid var(--ink); outline-offset: calc(-1 * var(--ts-focus-width)); }
.shell__acctopt[aria-current="page"] { font-weight: var(--w-semi); box-shadow: inset calc(var(--prose-unit) * 0.25) 0 0 var(--amber); }
.shell__acct form { margin: 0; }
/* A long display name never widens the bar; the full name stays in the button's aria-label. */
.shell__acctname { display: block; max-width: calc(var(--row) * 8); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (max-width: 640px) {
  .shell__acctname, .shell__acctcaret { display: none; }
  /* The avatar is the only way to Sign out here: a 44 px touch target, avatar centred. */
  .shell__acctbtn { padding: 0; min-width: var(--target-min); min-height: var(--target-min); justify-content: center; border-radius: 50%; }
}

.brand {
  display: inline-flex;
  align-items: center;
  /* The alt text keeps the wordmark's look when the image does not load. */
  font-weight: var(--w-semi);
  font-size: var(--fs-app-text-md);
  letter-spacing: var(--ts-tr-brand);
  color: inherit;
  text-decoration: none;
}
/* The ONE OE wordmark (assets/toolshed/oneoe-wordmark.png, 243×80, shown at control height). */
.brand__logo { display: block; height: var(--ctl-h-compact); width: auto; }

/* ——— Page ——— */
.page {
  width: 100%;
  max-width: var(--ts-page);
  margin: 0 auto;
  padding: var(--ts-page-top) var(--ts-pad-x) var(--ts-page-bottom);
  animation: page-in var(--dur-slow) var(--ease-standard);
}

.crumbs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--prose-unit);
  margin: 0 0 var(--ts-crumbs-gap);
  padding: 0;
  list-style: none;
  font-family: var(--font-mono);
  font-size: var(--fs-app-label-lg);
  letter-spacing: var(--tr-mono-wide);
  text-transform: uppercase;
  color: var(--fg-2);
  overflow-wrap: anywhere;
}
.crumbs li { min-width: 0; }
/* The dot and the first label stay together, centred like an eyebrow's dot. */
.crumbs li:first-child { display: flex; align-items: center; }
/* The amber dot that opens the trail (story 15.4): the page eyebrow's dot, moved here. */
.crumbs__dot { display: inline-block; width: var(--ts-dot); height: var(--ts-dot); margin-right: var(--prose-unit); border-radius: 50%; background: var(--amber); flex: none; }
.crumbs li + li::before { content: "/"; margin-right: var(--prose-unit); color: var(--fg-3); }
.crumbs a { text-decoration: none; }
.crumbs a:hover { color: var(--fg-1); }
.crumbs [aria-current="page"] { color: var(--fg-1); }

.page__head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--row);
  flex-wrap: wrap;
  margin-bottom: var(--ts-head-gap);
}
.page__headtext { max-width: var(--ts-headtext-max); min-width: 0; }
/* The home's head text spans the page (story 40.1); every other page keeps the cap. */
[data-page="home"] .page__headtext { max-width: none; flex: 1 1 auto; }
/* Balanced lines would stop the home headline short of the page width (story 40.1). */
[data-page="home"] .page__head h1 { text-wrap: pretty; }
.page__head h1 {
  /* No eyebrow above it since story 15.4: the crumbs gap alone sets the space above. */
  margin: 0 0 calc(var(--prose-unit) * 1.5);
  font-size: var(--fs-app-display-2xl);
  font-weight: var(--w-medium);
  letter-spacing: var(--tr-app-display-2xl);
  line-height: var(--ts-lh-head);
  text-wrap: balance;
  /* A long unbroken name (up to 80 characters) wraps instead of pushing the page sideways (story 12.2). */
  overflow-wrap: anywhere;
}
.page__lede {
  margin: 0;
  font-size: var(--fs-app-display-sm);
  letter-spacing: var(--tr-app-display-sm);
  line-height: 1.4;
  color: var(--fg-2);
  text-wrap: pretty;
}

/* ——— Sections ——— */
.section { margin-top: var(--ts-section-gap); }
.page__head + .section { margin-top: 0; }
[tabindex="-1"]:focus { outline: none; }
.section__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(var(--prose-unit) * 2);
  padding-bottom: calc(var(--prose-unit) * 1.75);
  margin-bottom: var(--row);
  border-bottom: var(--ts-hairline) solid var(--rule);
}

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(var(--ts-card-min), 100%), 1fr));
  gap: var(--ts-grid-gap);
}

/* ——— Link cards (initiatives, tools, years) ——— */
.linkcard { min-height: var(--ts-card-min-h); }
.linkcard .oec-card__title {
  font-size: var(--fs-app-display-md);
  letter-spacing: var(--tr-app-display-md);
  font-weight: var(--w-medium);
}
.linkcard .oec-card__body { flex: 1; }
/* An initiative name's last word, on home cards and initiative page heads (story 13.3). Colour
   only: the AA-safe amber for amber that carries words; same style and weight as the title. */
.name-accent { color: var(--amber-text); }
.linkcard .oec-card__foot { justify-content: space-between; }
.linkcard__meta { font-size: var(--fs-app-text-sm); color: var(--fg-1); }
/* Lucide arrow-right, or arrow-up-right when external, in .oec-icon (fix 19, story 12.3). */
.linkcard__arr {
  display: inline-flex;
  color: var(--fg-2);
  transition: transform var(--dur-fast) var(--ease-standard), color var(--dur-fast) var(--ease-standard);
}
.linkcard:hover .linkcard__arr { color: var(--amber-text); transform: translateX(calc(var(--prose-unit) * 0.5)); }

.yearcard .oec-card__title {
  font-family: var(--font-mono);
  font-size: var(--fs-app-display-lg);
  letter-spacing: var(--ts-tr-year);
  font-feature-settings: "tnum" 1;
}

/* ——— Picture IDs ——— */
.fieldcount { display: flex; justify-content: space-between; gap: calc(var(--prose-unit) * 2); }
.desc-cell { display: block; max-width: 36ch; font-size: var(--fs-app-text-xs); color: var(--fg-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mono-id {
  font-family: var(--font-mono);
  font-size: var(--fs-app-label-lg);
  letter-spacing: var(--tr-app-num);
  font-feature-settings: "tnum" 1;
  color: var(--fg-2);
}

/* ——— Forms ——— */
.stack { display: flex; flex-direction: column; gap: var(--row); }
/* ——— Notice (DESIGN.md Components; fix 24, story 12.5): the one notice. Paper-2 ground and an
   amber rule by default; `data-tone` info, warn or danger takes the status tokens; `data-size`
   compact is the sign-in panel's tighter padding. It carries no outer margin: its place does. ——— */
.notice {
  margin: 0;
  padding: calc(var(--prose-unit) * 1.75) calc(var(--prose-unit) * 2);
  border-left: var(--ts-notice-rule) solid var(--amber);
  background: var(--paper-2);
  font-size: var(--fs-app-text-sm);
  color: var(--fg-1);
}
.notice[data-size="compact"] { padding: calc(var(--prose-unit) * 1.5) calc(var(--prose-unit) * 1.75); }
.notice[data-tone="info"] { background: var(--status-info-soft); color: var(--status-info-text); border-color: var(--status-info-text); }
.notice[data-tone="warn"] { background: var(--status-warn-soft); color: var(--status-warn-text); border-color: var(--status-warn-text); }
.notice[data-tone="danger"] { background: var(--status-danger-soft); color: var(--status-danger-text); border-color: var(--status-danger-text); }
.notice strong { font-weight: var(--w-semi); }
/* A notice that opens a manage panel or one of its parts (Add in bulk, Add one moment, story 22.2) sits one row above what follows. */
.manage__panel > .notice,
.admin__addone > .notice { margin-bottom: var(--row); }
.drop {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: calc(var(--prose-unit) * 1.25);
  padding: calc(var(--prose-unit) * 2.5);
  border: var(--ts-hairline) dashed var(--control-border);
  background: var(--paper);
}
.drop[data-drag="true"] { border-color: var(--ink); background: var(--paper-2); }
.drop__name { font-size: var(--fs-app-text-sm); color: var(--fg-2); word-break: break-all; }
.actions { display: flex; gap: calc(var(--prose-unit) * 1.5); flex-wrap: wrap; align-items: center; }

.facts { display: grid; grid-template-columns: max-content 1fr; gap: calc(var(--prose-unit) * 1.25) var(--row); margin: 0; }
.facts dt { font-family: var(--font-mono); font-size: var(--fs-app-label-lg); letter-spacing: var(--tr-mono-wide); text-transform: uppercase; color: var(--fg-2); padding-top: calc(var(--prose-unit) * 0.25); }
.facts dd { margin: 0; }

.rowline { display: flex; align-items: center; justify-content: space-between; gap: var(--row); flex-wrap: wrap; padding: calc(var(--prose-unit) * 2.5) 0; border-bottom: var(--ts-hairline) solid var(--rule); }
.rowline__text { max-width: var(--ts-measure); }
/* A row holding a field and its button (Add member, Look up): the button lines up with the input,
   not with the label and input together, so the row aligns to the top and the button drops by the
   label's height (story 34.1). A hint or error under the input does not move it. */
.rowline:has(> .oec-field) { align-items: flex-start; }
.rowline > .oec-field .oec-field__label { line-height: 1.4; }
.rowline:has(> .oec-field) > .oec-btn { margin-top: var(--ts-label-offset); }
.rowline__title { margin: 0 0 calc(var(--prose-unit) * 0.5); font-size: var(--fs-app-text-lg); font-weight: var(--w-semi); }
.rowline__desc { margin: 0; font-size: var(--fs-app-text-sm); color: var(--fg-2); }

[hidden] { display: none !important; }

@keyframes page-in {
  from { opacity: 0; transform: translateY(var(--prose-unit)); }
  to   { opacity: 1; transform: none; }
}

/* Phone: the gutter, the account menu (above) and the one-column grids change together. */
@media (max-width: 640px) {
  .oe-product { --ts-pad-x: var(--ts-gutter-x-phone); }
  .shell__bar, .shell__foot { padding-top: var(--ts-bar-pad-y-phone); padding-bottom: var(--ts-bar-pad-y-phone); }
  .page { padding-top: var(--ts-page-top-phone); padding-bottom: var(--ts-page-bottom-phone); }
  .page__head { margin-bottom: var(--ts-head-gap-phone); }
  .grid { grid-template-columns: 1fr; }
}
@media (max-width: 480px) {
  .page__head h1 { font-size: var(--fs-app-display-xl); letter-spacing: var(--tr-app-display-xl); }
}

/* Wide content scrolls inside its own box, never the page. */
.tablewrap { overflow-x: auto; }
.tablewrap .oec-table { min-width: var(--ts-table-min); }
/* The Approvals and Removals tables gain a 64 px picture column (story 11.1). */
.tablewrap .oec-table:has(.thumbcell) { min-width: var(--ts-table-min-thumb); }
.oec-tabs { overflow-x: auto; scrollbar-width: none; }
.oec-tab { flex: none; }
.tablewrap td[data-mono="true"] { white-space: nowrap; }
.actions > .oec-btn { flex: none; }
/* Head actions keep their whole label ("Open Moments That Matter", fix 9, story 12.3), never past the page edge. */
#head-actions .oec-btn { max-width: 100%; }

/* ============================================================
   MTM year page and moment items
   Layout from design/claude-design/Moments That Matter 2026.dc.html,
   scaled from its 1620px canvas to the 1120px page. The design's
   colour literals are mapped to tokens.
   ============================================================ */
/* The year tabs sit between the page head and the grid (story 12.2), the category Select on the
   right (story 17.3); on a narrow screen the Select wraps below the tabs. */
.mtm-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: calc(var(--prose-unit) * 2);
  margin-bottom: calc(var(--prose-unit) * 4);
  border-bottom: var(--ts-hairline) solid var(--rule);
}
.mtm-strip .oec-tabs { border-bottom: 0; min-width: 0; }
/* Year tabs are page links: the current year carries aria-current, styled as the design system's selected tab. */
.oec-tab[aria-current="page"] { color: var(--fg-1); border-bottom-color: var(--amber); }
.oec-tab[aria-current="page"] .oec-tab__count { color: var(--amber-text); }
.mtm-strip + .section { margin-top: 0; }
.yearfilter { display: flex; align-items: center; gap: var(--prose-unit); margin-left: auto; padding-bottom: var(--prose-unit); }
.yearfilter .oec-field__label { white-space: nowrap; }
.yearfilter .oec-select { width: auto; max-width: 100%; }
/* On a phone the Select takes its own line, left-aligned under the tabs. */
@media (max-width: 640px) {
  .yearfilter { margin-left: 0; width: 100%; }
  .yearfilter .oec-select { flex: 1 1 auto; }
}

.mgrid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: calc(var(--prose-unit) * 5) var(--row); }

.mitem {
  display: flex;
  flex-direction: column;
  gap: calc(var(--prose-unit) * 1.5);
  min-width: 0;
  color: inherit;
  text-decoration: none;
  /* Its focus ring sits further out than a control's. */
  --ts-focus-offset: calc(2 * var(--ts-focus-width));
  --ts-focus-spread: var(--ts-focus-halo-wide);
}
.mitem__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(var(--prose-unit) * 2);
  padding-bottom: calc(var(--prose-unit) * 1.25);
  border-bottom: var(--ts-hairline) solid var(--rule);
  font-family: var(--font-mono);
  font-size: var(--fs-app-label-lg);
  letter-spacing: var(--tr-app-label-lg);
  text-transform: uppercase;
}
.mitem__name { color: var(--amber-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* The name gives way first; a long category truncates at --ts-cat-max (story 12.5). */
.mitem__cat { flex-shrink: 0; max-width: var(--ts-cat-max); color: var(--fg-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mitem__photo { position: relative; aspect-ratio: 4 / 3; overflow: hidden; background: var(--paper-2); }
.mitem__photo > :not(.framed, .mitem__reactions) {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: var(--ts-photo-filter);
}
.mitem__photo > :not(.mitem__reactions) { transition: scale var(--dur-base) var(--ease-standard); }
.mitem:hover .mitem__photo > :not(.mitem__reactions) { scale: 1.02; }
.mitem__desc {
  margin: 0;
  font-size: var(--fs-app-text-md);
  line-height: 1.45;
  letter-spacing: var(--tr-app-text-md);
  color: var(--fg-2);
  text-wrap: pretty;
  overflow-wrap: anywhere;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
/* … and 64% ink where it is: paper-on-dark counts stay ≥ 4.5:1 over a white photo (story 20.3). */
/* On `.oe-product`, where the token lives: on `:root` it would be shadowed (fixed in story 25.1). */
@supports (color: color-mix(in srgb, red 50%, transparent)) {
  .oe-product { --ts-photo-band: color-mix(in srgb, var(--ink) 64%, transparent); }
}
/* A year card's reactions above zero (story 17.3): emoji and count, read as "Fire, 3". They sit on a
   flat translucent ink band across the bottom of the picture, light counts on it (story 20.3; no
   gradient, per the design system); a card with no reactions shows no band. */
.mitem__reactions {
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; flex-wrap: wrap; gap: calc(var(--prose-unit) * 1.5);
  margin: 0; padding: var(--prose-unit) calc(var(--prose-unit) * 1.5);
  background: var(--ts-photo-band);
}
.mitem__reaction { display: inline-flex; align-items: center; gap: calc(var(--prose-unit) * 0.5); font-size: var(--fs-app-text-md); line-height: 1; }
.mitem__reactcount { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--fs-app-label-lg); color: var(--paper-on-dark); }

@media (max-width: 900px) {
  .mgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
  .mgrid { grid-template-columns: 1fr; }
}

/* ——— Shared in the last week (story 11.2): 3 per line on every width, at most 3 lines.
   Below 480 px the items show the picture only, as a centred square crop of the 4:3 framed view. ——— */
.mgrid.mgrid--week { grid-template-columns: repeat(3, minmax(0, 1fr)); }
/* The frame wraps the framed photo in the week grid only. `.mgrid--week .mitem__photo > .mitem__frame` (0,3,0)
   outranks the generic `.mitem__photo > :not(.framed)` (0,2,0), which would otherwise filter the frame and
   the photo twice; it does not rely on source order. */
.mgrid--week .mitem__photo > .mitem__frame { position: absolute; inset: 0; display: block; width: 100%; height: 100%; filter: none; }
.shared__more { margin-top: calc(var(--prose-unit) * 4); }
/* The list's ghost Button ("See more moments", story 16.2) shows its whole label, never cut at the 26ch Button ceiling. */
.shared__more .oec-btn { max-width: none; }
/* The week cards show name, category and picture only (story 16.2). Below 900 px three columns are
   narrow: stack name over category so each gets the whole column. */
@media (max-width: 900px) {
  .mgrid.mgrid--week { gap: calc(var(--prose-unit) * 4) calc(var(--prose-unit) * 2); }
  .mgrid--week .mitem__head { flex-direction: column; align-items: flex-start; gap: calc(var(--prose-unit) * 0.5); }
  .mgrid--week .mitem__name,
  .mgrid--week .mitem__cat { max-width: 100%; }
}
@media (max-width: 480px) {
  .mgrid.mgrid--week { gap: var(--prose-unit); }
  .mgrid--week .mitem { gap: 0; }
  .mgrid--week .mitem__head { display: none; }
  .mgrid--week .mitem__photo { aspect-ratio: 1 / 1; }
  .mgrid--week .mitem__photo > .mitem__frame { left: 50%; right: auto; width: calc(100% * 4 / 3); translate: -50% 0; }
  .shared__more { margin-top: var(--row); }
}

/* ——— Add page (design/claude-design/Add Moment.dc.html) ——— */
.addgrid {
  /* One column: Shared by, Category, photo, Description (owner change from the design's two columns).
     It fills the standard page (story 17.1), and since story 26.1 so does every row: fields, hints,
     counter, policy, confirmation and actions span the page with the photo frame. */
  padding-top: var(--prose-unit);
}
/* "Add your moment" (story 20.2) and the head buttons are short, fixed labels; the design system's
   26ch button cap cut the submit to "ADD YOUR MO" with the button's tracking (story 26.1). */
.addform__actions .oec-btn,
.page__head .actions .oec-btn { max-width: none; }
.addform { display: flex; flex-direction: column; gap: var(--row); min-width: 0; }
.addfield { display: flex; flex-direction: column; gap: var(--prose-unit); }
.addform__who {
  font-size: var(--fs-app-display-md);
  font-weight: var(--w-medium);
  letter-spacing: var(--tr-app-display-md);
  line-height: 1.2;
}
.addform__grow .oec-textarea { min-height: var(--ts-textarea-min-h); }
.addform__policy { margin: 0; font-size: var(--fs-app-text-sm); color: var(--fg-2); }
.addform__policy strong { color: var(--fg-1); font-weight: var(--w-semi); }
.addform__saved {
  padding: calc(var(--prose-unit) * 1.75) 0 0;
  border-top: var(--ts-hairline) solid var(--rule);
  font-size: var(--fs-app-text-lg);
  color: var(--fg-1);
}
.addform__saved a { color: var(--amber-text); }
.addform__actions {
  display: flex;
  justify-content: flex-end;
  gap: calc(var(--prose-unit) * 1.5);
  padding-top: calc(var(--prose-unit) * 2.5);
  border-top: var(--ts-hairline) solid var(--rule);
}

.addphoto { display: flex; flex-direction: column; gap: calc(var(--prose-unit) * 1.25); min-width: 0; }
.addphoto__drop {
  position: relative;
  aspect-ratio: 4 / 3;   /* same frame as the year page, so the framing carries over */
  padding: 0;
  align-items: stretch;
  justify-content: center;
  cursor: pointer;
  background: var(--paper-2);
  transition: border-color var(--dur-fast) var(--ease-standard), background var(--dur-fast) var(--ease-standard);
}
.addphoto__drop:hover { border-color: var(--fg-1); }
/* With a photo the box is the framing editor (frame-editor.js, story 36.3), as the Modal's frame. */
.addphoto__drop[data-filled="true"] { border-style: solid; border-color: var(--rule); cursor: grab; touch-action: none; }
.addphoto__drop[data-panning] { cursor: grabbing; }
.addphoto__placeholder { position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: calc(var(--prose-unit) * 2); flex: 1; padding: calc(var(--prose-unit) * 4); text-align: center; }
.addphoto__cta { font-size: var(--fs-app-display-sm); color: var(--fg-2); }
.addphoto__skel { position: absolute; inset: 0; --skh: 100%; }
.addphoto__skel .oec-skel__bar { height: 100%; }

/* Framed photo: positioned by framedStyle() in app.js, never cropped in the file. */
img.framed {
  position: absolute;
  max-width: none;
  transform: translate(-50%, -50%);
  object-fit: fill;
  filter: var(--ts-photo-filter);
  user-select: none;
  -webkit-user-drag: none;
}
.addframe__clip { position: absolute; inset: 0; overflow: hidden; }
/* The moment page's "Edit moment" Modal frames the photo as the add page does (story 14.7). */
.editframe { position: relative; aspect-ratio: 4 / 3; background: var(--paper-2); border: var(--ts-hairline) solid var(--rule); cursor: grab; touch-action: none; overflow: hidden; }
.editframe:active,
.editframe[data-panning] { cursor: grabbing; }
.addframe__ctl {
  position: absolute;
  top: var(--prose-unit);
  right: var(--prose-unit);
  display: flex;
  gap: calc(var(--prose-unit) * 0.75);
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease-standard);
}
.addframe__ctl .oec-btn { background: var(--paper); }
.addphoto__drop:hover .addframe__ctl,
.addphoto__drop:focus-within .addframe__ctl { opacity: 1; }
@media (hover: none) { .addframe__ctl { opacity: 1; } }
.addframe__tools { display: flex; align-items: center; flex-wrap: wrap; gap: calc(var(--prose-unit) * 1.5) calc(var(--prose-unit) * 2); padding: calc(var(--prose-unit) * 1.25) 0; border-bottom: var(--ts-hairline) solid var(--rule); }
.addframe__zoom { display: inline-flex; align-items: center; gap: calc(var(--prose-unit) * 1.25); }
.addframe__zoom input { width: calc(var(--prose-unit) * 20); accent-color: var(--ink); }
.addframe__help { flex: 1; min-width: calc(var(--prose-unit) * 22.5); font-size: var(--fs-app-text-xs); color: var(--fg-2); }
.addphoto__foot { display: flex; align-items: center; justify-content: space-between; gap: calc(var(--prose-unit) * 2); }

/* ——— Moment page (design/claude-design/Moments That Matter.dc.html) ——— */
.mview__fig { margin: 0; }
.mview__photo { display: flex; justify-content: center; background: var(--paper-2); }
.mview__photo img { display: block; max-width: 100%; max-height: var(--ts-photo-max-h); width: auto; height: auto; filter: var(--ts-photo-filter); }
.mview__desc {
  max-width: var(--ts-measure);
  margin: calc(var(--prose-unit) * 2.5) 0 0;
  font-size: var(--fs-app-text-2xl);
  line-height: 1.45;
  letter-spacing: var(--tr-app-text-2xl);
  color: var(--fg-2);
  text-wrap: pretty;
  overflow-wrap: anywhere;
}
/* The picture ID and the gallery link close the page, aligned right (stories 17.2 and 20.1). */
.mview__meta { margin: calc(var(--prose-unit) * 2.5) 0; font-size: var(--fs-app-text-sm); color: var(--fg-2); text-align: right; }
.mview__meta a { color: var(--amber-text); }
/* Reactions (story 14.8): compact ghost Buttons, the viewer's own pressed. The emoji are the
   design system's one emoji exception, here and in the year cards' counts only. Since story 23.1
   they sit in one column on the right of the photo, inside its gray box (the stage), which grows to
   fit them; each button takes the paper ground so it reads as a box on the gray. On a phone they
   drop below the photo, outside the box, as a wrapping row. */
.reactions { display: flex; flex-wrap: wrap; gap: var(--prose-unit); margin: calc(var(--prose-unit) * 2.5) 0 0; }
.mview__stage { display: flex; align-items: stretch; background: var(--paper-2); }
.mview__stage .mview__photo { flex: 1 1 auto; min-width: 0; align-items: center; }
.mview__stage .reactions { flex: none; flex-direction: column; flex-wrap: nowrap; margin: 0; padding: calc(var(--prose-unit) * 2); }
.mview__stage .reaction { justify-content: flex-start; background: var(--paper); }
.reaction { gap: calc(var(--prose-unit) * 0.75); }
/* 14px emoji (story 17.2). */
.reaction__emoji { font-size: var(--fs-app-text-md); line-height: 1; }
.reaction__count { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--fs-app-label-lg); color: var(--fg-2); }
.reaction[aria-pressed="true"] { border-color: var(--amber); background: var(--paper-2); }
/* On the gray stage the pressed one keeps the paper ground; the amber border marks it (story 23.1). */
.mview__stage .reaction[aria-pressed="true"] { background: var(--paper); }
@media (max-width: 640px) {
  .mview__stage { display: block; background: none; }
  .mview__stage .mview__photo { background: var(--paper-2); }
  .mview__stage .reactions { flex-direction: row; flex-wrap: wrap; margin: calc(var(--prose-unit) * 2.5) 0 0; padding: 0; }
  .mview__stage .reaction { background: none; }
  .mview__stage .reaction[aria-pressed="true"] { background: var(--paper-2); }
}
.reaction[aria-pressed="true"] .reaction__count { color: var(--amber-text); }

.mview__notice { margin: 0 0 calc(var(--prose-unit) * 2.5); }
/* The moment page's head is the year card's head (story 41.1): the name as the h1 in the card's
   amber mono capitals, the category in grey on the right, a hairline under them. A long name wraps. */
.mview__head { margin-bottom: var(--row); }
.mview__head h1 { margin: 0; font: inherit; }
/* Story 43.1 (owner): 16px bold for the name and the category; the category no longer truncates here. */
.mview__head .mitem__name { font-size: var(--fs-app-text-xl); font-weight: var(--ts-w-bold); white-space: normal; overflow-wrap: anywhere; }
.mview__head .mitem__cat { font-size: var(--fs-app-text-xl); font-weight: var(--ts-w-bold); max-width: none; }
/* "Request removal" (stories 6.3 and 14.6): a banner whose ghost Button opens the form in place.
   Without script (no `removal--js`) the banner's button and Cancel are hidden and the form shows. */
.removal { margin: calc(var(--prose-unit) * 2.5) 0 0; display: flex; flex-direction: column; gap: calc(var(--prose-unit) * 2); }
.removal__banner { display: flex; align-items: center; justify-content: space-between; gap: var(--row); flex-wrap: wrap; }
.removal__text { margin: 0; }
/* The engagement team's edit banner sits below the removal one, in its layout (story 17.2). */
.mview__edit { margin: calc(var(--prose-unit) * 2.5) 0 0; }
.removal:not(.removal--js) .removal__open,
.removal:not(.removal--js) .removal__cancel,
.removal--open .removal__open,
.removal--js:not(.removal--open) .removal__form { display: none; }
.removal__form { display: flex; flex-direction: column; gap: calc(var(--prose-unit) * 2); }
.removal .oec-textarea { width: 100%; box-sizing: border-box; }

/* ——— Manage page tabs (both manage pages, story 19.1) ———
   Equal-width tabs, each numbered "01", "02", … in amber mono, its label in sentence case and cut
   with an ellipsis when it does not fit. A strong rule runs over every tab, ink over the selected
   one, which also takes the card tint; a hairline closes the strip. The number is CSS generated
   content with empty alt text, so assistive tech reads only the label. Year tabs keep the design
   system's underline. */
.admin__tabs {
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 0;
  overflow: visible; margin-bottom: var(--row); counter-reset: ts-tab;
  border-bottom: var(--ts-hairline) solid var(--rule);
}
.admin__tabs .oec-tab {
  counter-increment: ts-tab; min-width: 0; margin: 0;
  justify-content: flex-start; gap: calc(var(--prose-unit) * 1.5);
  padding: calc(var(--prose-unit) * 2.5) calc(var(--prose-unit) * 4);
  border-bottom: 0; border-top: var(--ts-tab-rule) solid var(--rule-strong);
  font-family: var(--font-sans); font-size: var(--fs-app-text-xl); letter-spacing: var(--tr-app-text-xl);
  font-weight: var(--w-medium); text-transform: none; color: var(--fg-2);
  transition: color var(--dur-fast, 140ms) var(--ease-standard, ease), border-color var(--dur-fast, 140ms) var(--ease-standard, ease), background var(--dur-fast, 140ms) var(--ease-standard, ease);
}
.admin__tabs .oec-tab::before {
  content: counter(ts-tab, decimal-leading-zero) / "";
  flex: none; font-family: var(--font-mono); font-size: var(--fs-app-label-lg);
  letter-spacing: var(--tr-app-num); font-feature-settings: "tnum" 1; color: var(--amber-text);
}
.admin__tabs .oec-tab__lab { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.admin__tabs .oec-tab__count { flex: none; }
.admin__tabs .oec-tab:hover { color: var(--fg-1); }
.admin__tabs .oec-tab[aria-selected="true"] { color: var(--fg-1); background: var(--paper-2); border-top-color: var(--ink); }
/* Phone: two tabs a row, each with its own top rule, so every row reads the same (fix 4). */
@media (max-width: 640px) {
  .admin__tabs { grid-auto-flow: row; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .admin__tabs .oec-tab { padding: calc(var(--prose-unit) * 2) calc(var(--prose-unit) * 2); }
}
/* Both manage pages (story 10.4; fix 14, story 12.4; owner decision 2026-10-23). The inline
   script before the strip puts `js` and `data-tab` on <html>: from the first paint the strip shows
   with only the picked panel, and tabs.js keeps `data-tab` in step. Without script the strip is
   hidden (no dead buttons) and every panel stacks under its plain name (`.manage__panel-name`,
   stories 15.2 and 16.1), with the same gap as `.section`; the name shows only without
   script. A new manage page adds its panels to the list below. */
html:not(.js) .admin__tabs { display: none; }
html:not(.js) .manage__panel ~ .manage__panel { margin-top: var(--ts-section-gap); }
/* Removals: the remove-by-ID lookup sits a section below the requests (story 22.1); Add: the
   single add a section below the bulk import (story 22.2). */
.admin__removeby,
.admin__addone { margin-top: var(--ts-section-gap); }
/* A section head that is a heading (the panel names, Approvals' queue head) keeps the head's type. */
h2.section__head,
h3.section__head { margin-top: 0; font: inherit; }
.js .manage__panel-name { display: none; }
.js .manage__panel { display: none; }
.js[data-tab="approvals"] #panel-approvals,
.js[data-tab="removals"] #panel-removals,
.js[data-tab="add"] #panel-add,
.js[data-tab="categories"] #panel-categories,
.js[data-tab="team"] #panel-team,
.js[data-tab="initiatives"] #panel-initiatives,
.js[data-tab="home"] #panel-home { display: block; }
/* The error component (fix 16) sits on the page's left edge, with the crumbs and the h1 of
   every other page: no inline padding from the EmptyState's page size. */
.oec-empty.errstate { padding-left: 0; padding-right: 0; }
.admin__idfield { flex: 1; min-width: min(calc(var(--row) * 10), 100%); }
.admin__status { margin: calc(var(--prose-unit) * 2) 0 0; font-size: var(--fs-app-text-sm); color: var(--fg-1); }
.admin__moment {
  display: grid;
  grid-template-columns: minmax(0, calc(var(--prose-unit) * 27.5)) minmax(0, 1fr);
  gap: var(--row);
  align-items: start;
  padding: calc(var(--prose-unit) * 2.5) 0;
  border-bottom: var(--ts-hairline) solid var(--rule);
}
.admin__thumb { display: flex; justify-content: center; background: var(--paper-2); }
.admin__thumb img { display: block; max-width: 100%; max-height: calc(var(--row) * 10); width: auto; height: auto; filter: var(--ts-photo-filter); }
.admin__nophoto { padding: calc(var(--prose-unit) * 5) calc(var(--prose-unit) * 1.5); font-family: var(--font-mono); font-size: var(--fs-app-label-md); letter-spacing: var(--tr-mono); text-transform: uppercase; color: var(--fg-2); }
.admin__facts { display: flex; flex-direction: column; gap: calc(var(--prose-unit) * 2.5); min-width: 0; }
.admin__desc { overflow-wrap: anywhere; }
@media (max-width: 640px) {
  .admin__moment { grid-template-columns: minmax(0, 1fr); }
  .admin__moment .facts { grid-template-columns: minmax(0, 1fr); gap: calc(var(--prose-unit) * 0.5); }
  .admin__moment .facts dd { margin-bottom: var(--prose-unit); }
}

/* ——— Engagement page, Removals tab (/moments/admin#removals, story 6.3) ——— */
.removals__reasons { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: var(--prose-unit); }
.removals__reasons li { max-width: 40ch; overflow-wrap: anywhere; font-size: var(--fs-app-text-sm); }
.removals__who { font-weight: var(--w-semi); }
.removals__none { font-size: var(--fs-app-text-sm); color: var(--fg-2); }

/* ——— Engagement page, Approvals tab (/moments/admin#approvals, story 4.1) ——— */
.approvals__queue { margin-top: var(--prose-gap-h); }
.queue__badge { display: block; margin-top: var(--prose-unit); }
.queue__actions { justify-content: flex-end; flex-wrap: nowrap; }

/* ——— Approvals and Removals thumbnails (story 11.1) ———
   A 64 px square of the display rendition, cover-cropped, square corners (the system has no
   radius) and the rule hairline; the warm look as on every photo (AD-2). Without a picture the
   same square holds the picture ID in the mono label style. It stays 64 px at every width; the
   table scrolls inside .tablewrap, never the page. */
.thumbcell { width: calc(var(--ts-thumb) + 2 * var(--px, calc(var(--prose-unit) * 2))); }
.thumb {
  --thumb-size: var(--ts-thumb);
  display: flex;
  flex: none;
  width: var(--thumb-size);
  height: var(--thumb-size);
  box-sizing: border-box;
  border: var(--ts-hairline) solid var(--rule);
  background: var(--paper-2);
}
img.thumb { display: block; object-fit: cover; filter: var(--ts-photo-filter); }
.thumb--none { align-items: center; justify-content: center; padding: calc(var(--prose-unit) * 0.5); text-align: center; }
.thumb--none .oe-mono-label { line-height: 1.3; overflow-wrap: anywhere; word-break: break-all; }
/* The picture column takes the room the description preview gave up, so Approve and Reject stay in view at desktop width. */
.oec-table:has(.thumbcell) .desc-cell { max-width: 22ch; }
[data-page="moments-admin"] .oec-toast__body[data-mono="true"] { font-family: var(--font-mono); letter-spacing: var(--tr-mono); }
/* Toasts never run past a phone's edge (the stack pads by one row on each side). */
[data-page="moments-admin"] .oec-toaststack,
[data-page="manage"] .oec-toaststack { max-width: 100vw; box-sizing: border-box; }
@media (max-width: 640px) {
  [data-page="moments-admin"] .oec-toast,
  [data-page="manage"] .oec-toast { min-width: 0; max-width: calc(100vw - 2 * var(--row)); }
}

/* ——— Engagement page, Add tab, "Add in bulk" (/moments/admin#add, AD-18; story 22.2) ——— */
.import__pickers { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--row); }
.import__sample { color: var(--amber-text); }
.import__result { margin-top: calc(var(--prose-unit) * 4); }
.import__result:empty { display: none; }
.import__badges { display: flex; flex-direction: column; align-items: flex-start; gap: calc(var(--prose-unit) * 0.5); }
.import__result .oec-badge { white-space: nowrap; }
.import__result td { overflow-wrap: break-word; }
@media (max-width: 640px) {
  .import__pickers { grid-template-columns: minmax(0, 1fr); }
}

/* ——— Engagement page, Categories tab (/moments/admin#categories, story 4.2) ———
   Rows and save bar from the design system's templates/settings-page, as named classes. */
.vh {
  position: absolute;
  width: var(--ts-vh-size);
  height: var(--ts-vh-size);
  margin: calc(-1 * var(--ts-vh-size));
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
/* Room under the last row while the fixed save bar shows. */
.cats--bar { padding-bottom: calc(var(--row) * 4); }
.cats__head { margin-bottom: var(--prose-unit); }
.cats__desc { margin: 0; max-width: var(--prose-measure); font-size: var(--fs-app-text-xs); letter-spacing: var(--tr-app-text-xs); line-height: var(--prose-lh); color: var(--fg-2); text-wrap: pretty; }
.catlist { list-style: none; margin: 0; padding: 0; }
.catrow {
  display: flex;
  flex-wrap: wrap;
  gap: var(--prose-gap-p) var(--prose-gap-rule);
  align-items: flex-start;
  justify-content: space-between;
  padding: var(--row) 0;
  border-top: var(--ts-hairline) solid var(--rule);
}
/* The name field runs up to the move buttons, and the add field up to its button (story 29.1). */
.catrow__field { flex: 1 1 calc(var(--row) * 14); min-width: 0; }
.catrow__controls { display: flex; align-items: center; gap: var(--prose-unit); flex: none; }
.catrow__switch { min-width: calc(var(--row) * 4.5); margin-left: var(--prose-gap-p); }
.catadd { padding: var(--row) 0; border-top: var(--ts-hairline) solid var(--rule); }
.catadd__row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--prose-gap-p); }
.catadd__row .oec-input { flex: 1 1 calc(var(--row) * 9); min-width: 0; }
@keyframes savebar-in { from { transform: translateY(100%); } to { transform: translateY(0); } }
.savebar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 60;
  background: var(--ink);
  border-top: var(--ts-hairline) solid var(--ink);
  box-shadow: var(--elev-3);
  animation: savebar-in var(--dur-base) var(--ease-standard);
}
/* As wide as the page, with the page's side padding. */
.savebar__inner {
  max-width: var(--ts-page);
  margin: 0 auto;
  padding: calc(var(--prose-unit) * 1.5) var(--ts-pad-x);
  display: flex;
  align-items: center;
  gap: var(--prose-gap-p);
  flex-wrap: wrap;
  box-sizing: border-box;
}
.savebar__label {
  flex: 1;
  min-width: calc(var(--row) * 7.5);
  font-family: var(--font-mono);
  font-size: var(--fs-ui-badge);
  letter-spacing: var(--tr-mono-wide);
  text-transform: uppercase;
  color: var(--muted-on-dark);
}
.savebar[data-state="conflict"] .savebar__label { color: var(--paper-on-dark); }
/* Toasts sit above the save bar while it shows (admin-categories.js sets --savebar-h). */
[data-page="moments-admin"] .oec-toaststack[data-position^="bottom"] { bottom: var(--savebar-h, 0); }
@media (max-width: 640px) {
  .catrow { gap: calc(var(--prose-unit) * 1.5); }
  .catrow__switch { margin-left: var(--prose-unit); }
  .savebar__inner { gap: calc(var(--prose-unit) * 1.5); }
  .savebar__label { min-width: 100%; }
}
@media (prefers-reduced-motion: reduce) {
  .savebar { animation: none; }
}

/* ——— Sign-in screen (AD-7 /auth/login) ——— */
.login {
  flex: 1;
  display: grid;
  place-items: center;
  padding: calc(var(--prose-unit) * 6) calc(var(--prose-unit) * 2) calc(var(--prose-unit) * 9);
  animation: page-in var(--dur-slow) var(--ease-standard);
}
.login__panel {
  width: 100%;
  max-width: var(--ts-login-max);
  display: flex;
  flex-direction: column;
  gap: calc(var(--prose-unit) * 2);
  padding: calc(var(--prose-unit) * 5) calc(var(--prose-unit) * 4.5) calc(var(--prose-unit) * 4);
  background: var(--paper);
  border: var(--ts-hairline) solid var(--rule);
  box-shadow: var(--elev-2);
}
.login__title {
  margin: 0;
  font-size: var(--fs-app-display-xl);
  font-weight: var(--w-medium);
  letter-spacing: var(--tr-app-display-xl);
  line-height: 1.1;
}
.login__lede { margin: 0; font-size: var(--fs-app-text-lg); color: var(--fg-2); text-wrap: pretty; }
.login__domain { font-family: var(--font-mono); font-size: 0.9em; color: var(--fg-1); }
.login__google { margin-top: var(--prose-unit); width: 100%; max-width: none; gap: calc(var(--prose-unit) * 1.5); }
/* Google's mark keeps its own colours (Google sign-in branding); it is the only multi-colour glyph in the app.
   On the ink primary button it sits on a light tile so every colour keeps its contrast. */
.login__gtile {
  display: inline-flex;
  flex: none;
  padding: var(--ts-google-tile-pad);
  background: var(--ts-google-tile);
  border-radius: var(--ts-google-tile-radius);
}
.login__g { width: var(--icon-lg); height: var(--icon-lg); flex: none; }
.login__foot { margin: var(--prose-unit) 0 0; padding-top: calc(var(--prose-unit) * 2); border-top: var(--ts-hairline) solid var(--rule); font-size: var(--fs-app-text-xs); color: var(--fg-2); }
@media (max-width: 480px) {
  .login__panel { padding: calc(var(--prose-unit) * 3.5) calc(var(--prose-unit) * 2.5) var(--row); box-shadow: none; }
}

/* ——— Manage Toolshed, engagement team (/manage, story 4.3, moved by story 7.1) ——— */
.team__list { list-style: none; margin: 0; padding: 0; }
.teamrow { flex-wrap: nowrap; gap: var(--prose-gap-p); }
.teamrow__text { flex: 1 1 auto; min-width: 0; }
.teamrow__email { overflow-wrap: anywhere; }
.teamrow .oec-btn { flex: none; }
/* Manage Toolshed, Initiatives (stories 7.2 and 13.5): one row per initiative with its status label. */
.initlist { list-style: none; margin: 0; padding: 0; }
.initrow { gap: var(--prose-gap-p); }
.initrow__text { flex: 1 1 auto; min-width: 0; }
.initrow__name { margin: 0; overflow-wrap: anywhere; }
.initrow__status { flex: none; white-space: nowrap; }
/* Story 7.6: "Edit details" sits next to the status label (story 13.5); the pair wraps under the name on phones. */
.initrow__controls { display: flex; align-items: center; gap: var(--prose-gap-p); flex: none; }
/* The details editor (Modal): stacked Fields; the body scrolls when the screen is short. */
.detailsform { display: flex; flex-direction: column; gap: var(--prose-gap-p); }
/* Manage Toolshed, Home (story 40.1): the home page head's two Fields, then the save button. The Fields span
   the panel (story 44.1); the measure cap that held them at reading width went. */
.homeform { display: flex; flex-direction: column; gap: var(--prose-gap-p); }
.homeform__actions { display: flex; }

/* Admin "Add" tab (story 11.3): "Add another" under the confirmation. */
.addform__again { margin-top: calc(var(--prose-unit) * 1.5); }
