/* aice console — one file, top-to-bottom in page order.
   Chrome and type helpers are lifted verbatim from packages/marketing/src/site.css
   so the two aice-x surfaces read as one product; everything below the rule is
   the organization list, which the marketing site has no counterpart for.
   Night-ledger discipline (A-55): amber --color-fill is never a text color —
   primary buttons pair it with --color-fill-fg; text accents are --color-primary.
   Dark mode needs zero JS: tokens/colors.css flips on @media (prefers-color-scheme: dark). */

/* ---- base ---- */
/* The hidden attribute is the page's ONLY way of saying "not now", and any
   author `display` beats the UA sheet's display:none (that is how a signed-out
   visitor once saw a Sign out button — see .session[hidden] below). One rule,
   stated once, so no future section has to remember. */
[hidden] { display: none !important; }
body { margin: 0; background: var(--color-bg); color: var(--color-fg); font-family: var(--font-family); }
a { color: var(--color-link); }
/* A-89: scope the hover accent away from .btn — its specificity (0,1,1) beat
   .btn's color (0,1,0); on dark themes where primary matches the button fill,
   hovered button text vanished. Also keeps A-55's "amber is never a text color"
   discipline for filled buttons. */
a:not(.btn):hover { color: var(--color-primary); }
* { box-sizing: border-box; }

/* ---- header / footer chrome ---- */
.site-header { display: flex; align-items: center; gap: var(--space-4); padding: 18px 48px; border-bottom: 1px solid var(--color-border-subtle); }
.logo { height: 26px; display: block; }
.chrome-label { font-size: var(--text-xs); color: var(--color-fg-muted); border: 1px solid var(--color-border); border-radius: var(--radius-sm); padding: 2px 8px; }
.spacer { flex: 1; }
.session { display: flex; align-items: center; gap: var(--space-3); }
/* display:flex beats the hidden attribute's UA display:none — without this,
   a signed-out visitor sees a Sign out button for a session they don't have. */
.session[hidden] { display: none; }
.session-email { font-size: var(--text-sm); color: var(--color-fg-muted); }
.site-footer { display: flex; align-items: center; gap: var(--space-4); padding: var(--space-4) 48px; border-top: 1px solid var(--color-border); font-size: var(--text-sm); color: var(--color-fg-muted); }

/* ---- buttons (design-system/components/core/Button.jsx) ---- */
.btn { display: inline-flex; align-items: center; justify-content: center; font-family: var(--font-family); font-weight: var(--font-weight-medium); font-size: var(--text-md); color: var(--color-fill-fg); background: var(--color-fill); border: 1px solid transparent; border-radius: var(--radius-sm); padding: 10px 20px; cursor: pointer; text-decoration: none; transition: filter var(--motion-fast) var(--ease-out), background var(--motion-fast) var(--ease-out), transform var(--motion-fast) var(--ease-out); }
.btn:hover { filter: brightness(1.08); }
.btn:disabled { opacity: .6; cursor: default; }
.btn-sm { padding: 6px 14px; font-size: var(--text-sm); }
.btn-secondary { color: var(--color-fg); background: transparent; border-color: var(--color-border); }
.btn-secondary:hover { background: var(--color-surface-muted); filter: none; }
/* A-48: one entry per sign-in provider, side by side and wrapping on a narrow
   screen rather than overflowing it. */
.signin-choices { display: flex; flex-wrap: wrap; gap: var(--space-3); }

/* ---- layout + type helpers ---- */
.col { max-width: 760px; margin: 0 auto; padding: 64px 24px 80px; }
.h-section { font-family: var(--font-family-display); font-weight: var(--font-weight-semibold); letter-spacing: var(--tracking-display); font-size: var(--text-3xl); margin: 0 0 var(--space-3); }
.lede { color: var(--color-fg-muted); font-size: var(--text-lg); line-height: var(--line-height-loose); margin: 0 0 var(--space-5); max-width: 56ch; }
.mono { font-family: var(--font-family-mono); }
.muted { color: var(--color-fg-muted); }

/* ---- tenant list ---- */
.tenant-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-2); }
.tenant { display: flex; align-items: center; gap: var(--space-4); background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: var(--space-4); }
.tenant-name { font-weight: var(--font-weight-medium); }
.tenant-host { margin-left: auto; font-size: var(--text-sm); color: var(--color-fg-muted); text-decoration: none; }
.tenant-host:hover { color: var(--color-primary); text-decoration: underline; }

/* A-114: a full row must get TALLER, never wider than its own card.
   A flex item floors at its min-content width, so a row carrying the extra
   grace/suspended content (the trial sentence, and a second host link when a
   custom domain is live) could not shrink to fit: the single line overflowed
   and the LAST item — the Settings button — hung outside the border. The name
   and the host say they can yield: `min-width: 0` lets the box shrink past
   min-content, and `overflow-wrap: anywhere` reflows the text inside the
   shrunken box instead of spilling out of it — the same treatment
   `.mono.block` gives a redirect URI. The two things that must stay whole to
   stay readable — the status pill and the button — are pinned with
   `flex: none`; the trial sentence below yields by wrapping. Content length,
   not viewport width, is what overfills a row, so this is unconditional rather
   than another breakpoint. */
.tenant-name, .tenant-host { min-width: 0; overflow-wrap: anywhere; }
.tenant-status, .tenant-settings { flex: none; }

/* A-118: WHERE the squeeze lands, now that A-114 made everything squeezable.
   Flexbox spreads a row's deficit in proportion to shrink factor × base size,
   so with the default factor of 1 every item lost the same fraction — and the
   display name, the shortest item, hit `overflow-wrap: anywhere` first: on the
   suspended + custom-domain row the name box fell to 60px and split
   `Residences` mid-word. This ladder says which text is worth the pixels: the
   trial sentence yields first (it is prose, and wrapping is what prose does),
   the hostnames next (monospace, and already broken across lines wherever a
   space serves one), the display name last.

   The name's factor stays at 1 and MUST NOT go below it. Flexbox scales the
   absorbed deficit by the sum of the unfrozen factors when that sum is under
   one, so a name left alone as the last unfrozen item with `flex-shrink: 0.25`
   soaks up only a quarter of the overflow and the row spills again — measured,
   not theorized. `flex-shrink: 0` is the same trap with none of the ambiguity.
   Weighting is safe because it only reorders who yields, never whether. */
.tenant-name { flex-shrink: 1; }
.tenant-host { flex-shrink: 2; }
.tenant-trial { flex-shrink: 3; }

/* Status is the one thing on this page an owner scans for, so it gets colour.
   Each token pair already carries a light and a dark value. */
.tenant-status { font-size: var(--text-xs); font-family: var(--font-family-mono); border-radius: var(--radius-sm); padding: 3px 10px; background: var(--color-surface-muted); color: var(--color-fg-muted); white-space: nowrap; }
.status-active { background: var(--color-success-soft); color: var(--color-success); }
.status-past_due, .status-grace { background: var(--color-warning-soft); color: var(--color-warning); }
.status-suspended, .status-deprovisioning { background: var(--color-danger-soft); color: var(--color-danger); }

/* Trial state (A-36). Quieter than the status pill beside it — it is a
   sentence, not a label — until the space actually stops serving, which is the
   one thing an owner must not scroll past. A-114: it wraps at every width. A
   sentence held on one line is a sentence that cannot shrink, and the row it
   sits in has to fit a button after it. */
.tenant-trial { font-size: var(--text-xs); color: var(--color-fg-muted); }
.tenant-trial.trial-suspended { color: var(--color-danger); }

/* ---- IdP wizard (A-39) ---- */
.steps { color: var(--color-fg-muted); line-height: var(--line-height-loose); padding-left: var(--space-5); margin: 0 0 var(--space-5); }
.steps li { margin-bottom: var(--space-3); }
.steps strong { color: var(--color-fg); font-weight: var(--font-weight-medium); }

/* The two values an owner copies. Block, selectable, and allowed to wrap —
   a redirect URI truncated by an ellipsis is a support ticket. */
.mono.block { display: block; margin-top: var(--space-2); padding: var(--space-3); background: var(--color-surface-muted); border: 1px solid var(--color-border); border-radius: var(--radius-sm); font-size: var(--text-sm); color: var(--color-fg); overflow-wrap: anywhere; user-select: all; }
.copy-btn { margin-top: var(--space-2); }

.connect-provider { border: 1px solid var(--color-border); border-radius: var(--radius-sm); padding: var(--space-3) var(--space-4); margin: 0 0 var(--space-5); display: flex; flex-wrap: wrap; gap: var(--space-4); }
.connect-provider legend { font-size: var(--text-sm); font-weight: var(--font-weight-medium); padding: 0 var(--space-2); }
.connect-provider label { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-sm); }
.connect-well { margin: 0 0 var(--space-5); }
/* A-550: the passage-destination options are sentences, not two-word labels, so
   they stack and their radio sits at the first line rather than centred against
   a three-line consequence. Everything else is `.connect-provider`'s. */
#storage-vectors { flex-direction: column; gap: var(--space-3); }
#storage-vectors label { align-items: flex-start; max-width: 72ch; line-height: var(--line-height-loose); }
#storage-vectors label input[type="radio"] { margin-block-start: 3px; flex: none; }
#storage-vectors input[type="text"] { font-family: var(--font-family-mono); font-size: var(--text-sm); color: var(--color-fg); background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-sm); padding: 6px 10px; inline-size: min(100%, 64ch); }
.connect-well p { margin: 0 0 var(--space-2); font-weight: var(--font-weight-medium); color: var(--color-fg); }
.connect-form { display: flex; flex-direction: column; gap: var(--space-2); }
.connect-form label { font-size: var(--text-sm); font-weight: var(--font-weight-medium); }
.connect-form input { font-family: var(--font-family-mono); font-size: var(--text-sm); color: var(--color-fg); background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-sm); padding: 10px 12px; margin-bottom: var(--space-3); }
.connect-form input:focus { outline: 2px solid var(--color-primary); outline-offset: 1px; }
/* A-548: the Front page section's delegation list. */
.front-page-managers { list-style: none; margin: 0 0 var(--space-3); padding: 0; display: flex; flex-direction: column; gap: var(--space-2); }
.front-page-manager { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); padding: 10px 12px; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-surface); }
.small { font-size: var(--text-sm); margin: 0 0 var(--space-4); max-width: 56ch; }
.connect-actions { display: flex; gap: var(--space-3); }

/* Success and refusal both land here; colour is the only difference, and the
   text says which either way. */
.connect-result { margin-top: var(--space-4); padding: var(--space-3) var(--space-4); border-radius: var(--radius-sm); background: var(--color-surface-muted); color: var(--color-fg); line-height: var(--line-height-loose); }
.connect-result.ok { background: var(--color-success-soft); color: var(--color-success); }
.connect-result.failed { background: var(--color-danger-soft); color: var(--color-danger); }

.tenant-settings { font-size: var(--text-sm); }

/* ---- settings hub (A-49) ----
   One tenant, one header, a section nav beneath. Future per-tenant surfaces
   (branding, members, deletion, billing, storage) are one nav entry + one
   .hub-section each — never a new row button. */
.hub-back { display: inline-block; font-size: var(--text-sm); color: var(--color-fg-muted); text-decoration: none; margin-bottom: var(--space-4); }
.hub-back:hover { color: var(--color-primary); }
.hub-head .h-section { margin-bottom: var(--space-1); }
.hub-host { margin: 0; color: var(--color-fg-muted); font-size: var(--text-sm); }
#hub-status { margin: var(--space-2) 0 0; }
.hub-nav { display: flex; gap: var(--space-2); border-bottom: 1px solid var(--color-border); margin: var(--space-5) 0; }
.hub-nav-link { padding: var(--space-2) var(--space-3); font-size: var(--text-sm); color: var(--color-fg-muted); text-decoration: none; border-bottom: 2px solid transparent; margin-bottom: -1px; transition: color var(--motion-fast) var(--ease-out), border-color var(--motion-fast) var(--ease-out); }
.hub-nav-link:hover { color: var(--color-fg); }
.hub-nav-link[aria-current="true"] { color: var(--color-fg); border-bottom-color: var(--color-primary); }
.h-sub { font-family: var(--font-family-display); font-weight: var(--font-weight-semibold); letter-spacing: var(--tracking-display); font-size: var(--text-xl); margin: 0 0 var(--space-3); }

/* ---- address section (A-47) ---- */
.address-list { list-style: none; margin: 0 0 var(--space-5); padding: 0; display: flex; flex-direction: column; gap: var(--space-1); }
.address-list li { font-size: var(--text-sm); }

/* ---- storage section (A-28) ---- */
.storage-checks { list-style: none; margin: 0 0 var(--space-4); padding: 0; display: flex; flex-direction: column; gap: var(--space-1); }
.storage-check { font-size: var(--text-sm); color: var(--color-fg-muted); }
.storage-check.check-ok { color: var(--color-success); }
.storage-check.check-failed { color: var(--color-danger); }

/* ---- branding editor (A-40) ----
   Chrome only. Every colour here is a night-ledger token: the candidate values
   an admin is trying out exist ONLY inside the preview frames' srcdoc, which is
   the boundary the section is built around. */
.h-mini { font-family: var(--font-family-display); font-weight: var(--font-weight-semibold); font-size: var(--text-md); margin: var(--space-5) 0 var(--space-2); }
.locked-note { background: var(--color-warning-soft); color: var(--color-warning); border-radius: var(--radius-sm); padding: var(--space-3) var(--space-4); line-height: var(--line-height-loose); max-width: 56ch; }

.tier-bar { display: flex; flex-wrap: wrap; gap: var(--space-2); margin: 0 0 var(--space-4); }
.tier-bar .btn[aria-pressed="true"] { color: var(--color-fill-fg); background: var(--color-fill); border-color: transparent; }
.tier-panel { margin-bottom: var(--space-4); }

.field-row { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-3); margin-bottom: var(--space-3); }
.field-row label { font-size: var(--text-sm); font-weight: var(--font-weight-medium); min-width: 9ch; }
.field-row input[type="color"] { inline-size: 48px; block-size: 32px; padding: 2px; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-sm); cursor: pointer; }
.field-row input[type="text"], .field-row select { font-family: var(--font-family); font-size: var(--text-sm); color: var(--color-fg); background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-sm); padding: 6px 10px; }
.field-row input[type="file"] { font-size: var(--text-sm); color: var(--color-fg-muted); max-width: 100%; }

/* The full ramp. A three-column grid so the two modes line up down the page —
   scanning "is dark right too?" is the whole reason both are shown at once. */
.palette-head, .palette-row { display: grid; grid-template-columns: minmax(0, 24ch) 56px 56px; justify-content: start; align-items: center; gap: var(--space-3); }
.palette-head { padding-bottom: var(--space-2); border-bottom: 1px solid var(--color-border-subtle); }
.palette-row { padding: var(--space-1) 0; }
.palette-role { font-size: var(--text-xs); color: var(--color-fg-muted); overflow-wrap: anywhere; }
.palette-row input[type="color"] { inline-size: 100%; block-size: 28px; padding: 2px; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-sm); cursor: pointer; }

/* A-74: the suggested brands. Swatch, hex, where it came from, and — when the
   contrast gate refuses it — the refusal, so a candidate is never offered as
   though it were acceptable. Each is a button because choosing one only fills
   the candidate; nothing here saves. */
.swatches { list-style: none; margin: 0 0 var(--space-4); padding: 0; display: flex; flex-wrap: wrap; gap: var(--space-2); }
.swatch { display: inline-flex; align-items: center; gap: var(--space-2); font-family: var(--font-family); font-size: var(--text-sm); color: var(--color-fg); background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-sm); padding: 6px 12px 6px 6px; cursor: pointer; text-align: start; }
.swatch:hover { background: var(--color-surface-muted); }
.swatch-chip { inline-size: 28px; block-size: 28px; border-radius: var(--radius-sm); border: 1px solid var(--color-border-subtle); flex: none; }
.swatch-lines { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.swatch-hex { font-family: var(--font-family-mono); font-size: var(--text-xs); }
.swatch-note { font-size: var(--text-xs); color: var(--color-fg-muted); overflow-wrap: anywhere; }
.swatch-refused .swatch-note { color: var(--color-danger); }
/* A-327: the whole brand, above the sandboxed frames. The strip is a summary —
   an observed role carries a ring so it is distinguishable from a derived one —
   and the logo is drawn from the returned payload as a data: URL, never from the
   fetched site's origin. */
.swatch { align-items: flex-start; }
.swatch-strip { display: flex; align-items: center; flex-wrap: wrap; gap: 3px; margin-top: 2px; }
.swatch-strip-label { font-family: var(--font-family-mono); font-size: var(--text-xs); color: var(--color-fg-muted); margin-inline-end: var(--space-1); }
.swatch-dot { inline-size: 12px; block-size: 12px; border-radius: 2px; border: 1px solid var(--color-border-subtle); flex: none; }
.swatch-dot-observed { border-color: var(--color-fg-muted); outline: 1px solid var(--color-fg-muted); outline-offset: 1px; }
.swatch-logo { max-inline-size: 96px; max-block-size: 24px; object-fit: contain; align-self: center; margin-inline-start: var(--space-2); }

.optin { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-sm); color: var(--color-fg-muted); margin-bottom: var(--space-4); }

.preview-pair { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3); }
.preview { margin: 0; min-width: 0; }
.preview figcaption { margin-bottom: var(--space-1); }
.preview iframe { display: block; width: 100%; height: 400px; border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface); }

.refusals { list-style: none; margin: var(--space-4) 0 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-1); }
.refusal { font-size: var(--text-sm); background: var(--color-danger-soft); color: var(--color-danger); border-radius: var(--radius-sm); padding: var(--space-2) var(--space-3); overflow-wrap: anywhere; }

.confirm { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-3); margin-top: var(--space-3); font-size: var(--text-sm); color: var(--color-fg-muted); }

/* ---- loading skeleton (A-49) ----
   The page's shape before its data; content settles into it, never pops. */
.skeleton { border-radius: var(--radius-sm); background: linear-gradient(90deg, var(--color-surface-muted) 25%, var(--color-surface) 50%, var(--color-surface-muted) 75%); background-size: 200% 100%; }
.skeleton-title { height: 38px; width: 40%; margin-bottom: var(--space-5); }
.skeleton-row { height: 58px; margin-bottom: var(--space-2); }

/* ---- motion (A-49) ----
   Micro-interactions only: durations and easings come from the tokens, the
   whole block yields to prefers-reduced-motion, and nothing here delays a
   task — every animation follows a state change the page already made. */
@media (prefers-reduced-motion: no-preference) {
  .skeleton { animation: shimmer 1.2s linear infinite; }
  .panel, .hub-section { animation: settle-in var(--motion-base) var(--ease-out); }
  .tenant { animation: row-in var(--motion-base) var(--ease-out) backwards; }
  .tenant:nth-child(2) { animation-delay: 50ms; }
  .tenant:nth-child(3) { animation-delay: 100ms; }
  .tenant:nth-child(n+4) { animation-delay: 150ms; }
  .connect-result, #domain-records { animation: settle-in var(--motion-base) var(--ease-out); }
  .btn:active { transform: scale(0.985); }
  .copy-btn.copied { animation: copy-pop var(--motion-base) var(--ease-out); }
  .tenant-status { transition: background var(--motion-base) var(--ease-out), color var(--motion-base) var(--ease-out); }
}
/* A-69 — the Features section. Rows are a LIST over the shared registry, so
   nothing here is keyed to an individual setting. Existing tokens only. */
.feature-row { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: var(--space-4); margin-bottom: var(--space-3); max-width: 56ch; }
.feature-row-head { display: flex; align-items: baseline; gap: var(--space-3); }
.feature-label { margin: 0; }
.feature-badge { margin-left: auto; font-family: var(--font-family-mono); font-size: var(--text-xs); background: var(--color-surface-muted); border-radius: var(--radius-sm); padding: 3px 10px; white-space: nowrap; }
.feature-description { margin: var(--space-2) 0 0; line-height: var(--line-height-loose); }
.feature-note { margin: var(--space-2) 0 var(--space-3); line-height: var(--line-height-loose); }
.feature-locked { margin: 0 0 var(--space-3); font-size: var(--text-sm); }
.feature-toggle:disabled { opacity: 0.55; cursor: not-allowed; }

/* A-26 — the Billing section. Plan rows reuse the .feature-row card above
   deliberately: they are the same object (a titled card with a badge and one
   action), and a second card style would be two things to keep in step.
   Existing tokens only. */
.billing-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); gap: var(--space-3); margin: var(--space-4) 0; max-width: 56ch; }
.billing-facts div { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: var(--space-3) var(--space-4); }
.billing-facts dt { margin: 0; }
.billing-facts dd { margin: var(--space-1) 0 0; overflow-wrap: anywhere; }

@keyframes shimmer { to { background-position: -200% 0; } }
@keyframes settle-in { from { opacity: 0; transform: translateY(4px); } }
@keyframes row-in { from { opacity: 0; transform: translateY(6px); } }
@keyframes copy-pop { 30% { transform: scale(1.08); } }

@media (max-width: 640px) {
  .site-header, .site-footer { padding-left: 20px; padding-right: 20px; }
  .site-header { flex-wrap: wrap; row-gap: var(--space-2); }
  .tenant { flex-wrap: wrap; gap: var(--space-2); }
  .tenant-host { margin-left: 0; width: 100%; }
  .hub-nav { flex-wrap: wrap; }
  /* A-40: two preview frames side by side stop being previews at phone width —
     stack them, and let the palette's mode columns narrow rather than push. */
  .preview-pair { grid-template-columns: minmax(0, 1fr); }
  .palette-head, .palette-row { grid-template-columns: minmax(0, 1fr) 44px 44px; gap: var(--space-2); }
  .field-row label { min-width: 0; width: 100%; }
  /* A-69: the badge is the longest thing on a feature row's head line. */
  .feature-row-head { flex-wrap: wrap; }
  .feature-badge { margin-left: 0; }
}
