/*
 * The shared layer of the employee screens.
 *
 * Every value here is transcribed from docs/sso-employee-signin-design-book.html, which is the
 * project's design system. Raw values live ONLY in this file: an etalon links it and never
 * restates it. The card's own styling lives here too, small-screen behaviour included, because
 * an etalon that carried its own layout would be a copy of the layer rather than a use of it.
 */

:root {
  /* Native controls and scrollbars are drawn by the browser from this declaration, not from the
     palette: without it they stay light while the dark palette below applies. */
  color-scheme: light dark;

  --color-paper: #eff1ef;
  --color-card: #ffffff;
  --color-ink: #16211e;
  --color-ink-2: #3d4a46;
  --color-muted: #63706b;
  --color-rule: #dee3e0;
  --color-rule-strong: #c6cfcb;
  --color-field: #ffffff;
  --color-field-disabled: #f1f3f1;
  --color-accent: #0e5c4f;
  --color-accent-ink: #ffffff;
  --color-accent-hover: #0a4a40;
  --color-accent-soft: #e4eeea;
  --color-danger: #9c2f27;
  --color-danger-soft: #f7e9e7;
  --color-ok: #1f6b4e;
  --color-ok-soft: #e5f0ea;
  --color-focus: #0e5c4f;

  --radius-field: 6px;
  --radius-card: 10px;

  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-7: 32px;
  --space-8: 40px;
  --space-9: 56px;

  --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial,
    sans-serif;
  /* For identifiers and secrets an administrator copies letter by letter: the system's own
     monospace, no web font, like the sans. */
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;

  --text-xs: 12px;
  --text-sm: 13px;
  --text-label: 13.5px;
  --text-body: 14px;
  --text-lead: 15px;
  --text-value: 16px;
  --text-heading: 25px;
  /* One digit of a sign-in code in its own cell: larger than a value, because a cell holds one
     glyph that is read at arm's length and compared with a letter on a phone. */
  --text-code: 24px;

  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-heading: 650;

  --leading-tight: 1.25;
  --leading-body: 1.5;

  --tracking-heading: -0.022em;
  --tracking-body: -0.011em;

  --hairline: 1px;
  --focus-halo: 3px;

  /* The page field. The lattice pitch is the spacing scale's own step, so the background is
     measured in the same units as everything standing on it; the dot is a hairline wide. The
     pool of light is an ellipse wider than the card, so its edge never coincides with the
     card's and never reads as a second border. */
  --lattice-ink: rgba(22, 33, 30, 0.1);
  --lattice-dot: 1px;
  --lattice-pitch: var(--space-6);
  --page-glow: rgba(255, 255, 255, 0.9);
  --page-glow-width: 900px;
  --page-glow-height: 620px;
  /* The book's card is 380px, which leaves 332px of content: its own direct-arrival sentence,
     "Sign in to see the applications you have access to.", does not fit on one line there. Widened
     on the owner's instruction so that sentence stays whole. A DEVIATION from the book's value. */
  --card-width: 440px;
  --accent-rule: 3px;
  --mark-size: 22px;
  --monogram-size: 36px;
  --glyph-size: 18px;
  --control-height: 42px;

  /* The administration panel: a rail of sections on the paper beside one wide surface, and a
     scrim under its dialogs. The rail fits the longest section name at body size beside the brand
     lockup. The page is capped rather than fluid, for the reason the card is 440px and not the
     window: a row is read, not stretched. The cap is set by the widest table, the audit trail's
     five columns, and is one value for every page so the panel breathes the same way in every
     section; raised from 960 on the owner's instruction after a look at a 1800px window. The
     scrim is the ink at low opacity, so a dimmed page still reads as this page. */
  --rail-width: 220px;
  --page-width: 1200px;
  /* The one exception to the shared cap: a page whose content is a wide table — the audit trail
     with its filters beside it — takes this cap instead, on the owner's instruction. */
  --page-width-wide: 1480px;
  --color-scrim: rgba(22, 33, 30, 0.45);
  /* The gap between a link and its underline, the value the card footer already uses by hand. */
  --underline-offset: 2px;

  /* Letters: the width mail clients give a message, and the width of a phone the letter must
     survive. The letter etalons show a letter at each; the letter itself is drawn by
     email-shell.js from the values of this file. */
  --email-width: 600px;
  --phone-width: 360px;

  /* Five hues for the five applications the project will ever hold, worn by the application tags
     in the panel's lists. Colour here is IDENTITY, never state — the name is always on the tag,
     the hue only lets the eye find the same application across two hundred rows — so none of the
     five is a status colour: not the accent, not ok, not danger. Muted to the saturation of the
     accent, so they read as chosen rather than generated. A DEVIATION from the book's palette on
     the owner's instruction. */
  --color-tag-1-soft: #e3ecf5;
  --color-tag-1-ink: #234b73;
  --color-tag-2-soft: #f6eedc;
  --color-tag-2-ink: #6b4f14;
  --color-tag-3-soft: #efe5f1;
  --color-tag-3-ink: #5d3466;
  --color-tag-4-soft: #eaecee;
  --color-tag-4-ink: #4b545b;
  --color-tag-5-soft: #f5e7e0;
  --color-tag-5-ink: #7a4a2e;
}

@media (prefers-color-scheme: dark) {
  :root {
    --color-paper: #101512;
    --color-card: #171e1b;
    --color-ink: #e7ece9;
    --color-ink-2: #b9c4bf;
    --color-muted: #8b9a94;
    --color-rule: #262f2b;
    --color-rule-strong: #3a453f;
    --color-field: #101512;
    --color-field-disabled: #1b221f;
    --color-accent: #55b39c;
    --color-accent-ink: #0b120f;
    --color-accent-hover: #6bc3ad;
    --color-accent-soft: #182a25;
    --color-danger: #e08a80;
    --color-danger-soft: #2a1b19;
    --color-ok: #6fbf97;
    --color-ok-soft: #16241d;
    --color-focus: #55b39c;

    /* Dark reverses both: the dots lift off the field instead of sinking into it, and the pool of
       light is a trace of the accent rather than white, which on a near-black field would read as
       haze rather than depth. */
    --lattice-ink: rgba(231, 236, 233, 0.07);
    --page-glow: rgba(85, 179, 156, 0.06);
    --color-scrim: rgba(0, 0, 0, 0.6);
    --color-tag-1-soft: #17273a;
    --color-tag-1-ink: #9cc1f0;
    --color-tag-2-soft: #2a2416;
    --color-tag-2-ink: #d8bb78;
    --color-tag-3-soft: #281c2c;
    --color-tag-3-ink: #cfa5d8;
    --color-tag-4-soft: #24282b;
    --color-tag-4-ink: #b5bcc2;
    --color-tag-5-soft: #2b1f19;
    --color-tag-5-ink: #d8a98f;
  }
}

[data-theme="dark"] {
  --color-paper: #101512;
  --color-card: #171e1b;
  --color-ink: #e7ece9;
  --color-ink-2: #b9c4bf;
  --color-muted: #8b9a94;
  --color-rule: #262f2b;
  --color-rule-strong: #3a453f;
  --color-field: #101512;
  --color-field-disabled: #1b221f;
  --color-accent: #55b39c;
  --color-accent-ink: #0b120f;
  --color-accent-hover: #6bc3ad;
  --color-accent-soft: #182a25;
  --color-danger: #e08a80;
  --color-danger-soft: #2a1b19;
  --color-ok: #6fbf97;
  --color-ok-soft: #16241d;
  --color-focus: #55b39c;

  --lattice-ink: rgba(231, 236, 233, 0.07);
  --page-glow: rgba(85, 179, 156, 0.06);
  --color-scrim: rgba(0, 0, 0, 0.6);
  --color-tag-1-soft: #17273a;
  --color-tag-1-ink: #9cc1f0;
  --color-tag-2-soft: #2a2416;
  --color-tag-2-ink: #d8bb78;
  --color-tag-3-soft: #281c2c;
  --color-tag-3-ink: #cfa5d8;
  --color-tag-4-soft: #24282b;
  --color-tag-4-ink: #b5bcc2;
  --color-tag-5-soft: #2b1f19;
  --color-tag-5-ink: #d8a98f;
}

/* --- the hidden attribute ------------------------------------------------
 * The browser implements [hidden] as display: none in its own stylesheet, which any author rule
 * setting display outranks. Every element in these etalons that is shown and hidden by state is
 * also given a display of its own, so without this one line a hidden message renders as an empty
 * box. Declared once here rather than guarded per selector, because the next selector to grow a
 * display would silently lose the guard.
 */

[hidden] {
  display: none !important;
}

/* --- the page ------------------------------------------------------------ */

/* The field is not one flat colour. Two layers, both decoration and neither carrying state: a
   lattice of dots on the spacing scale's pitch, and above it a soft pool of light centred slightly
   high, so the card sits IN something instead of floating ON it. The light is painted over the
   lattice on purpose — the dots fade out where the card meets them, which keeps the pattern from
   crowding the one thing that matters on the screen. The rule is a class rather than body.screen
   because two kinds of element wear it: an etalon and a served screen put it on the body, the
   administration panel's threshold on a wrapper inside its root — the same field either way. */
.screen {
  display: flex;
  min-height: 100vh;
  min-height: 100dvh;
  margin: 0;
  padding: var(--space-8) var(--space-4);
  background-color: var(--color-paper);
  background-image:
    radial-gradient(
      ellipse var(--page-glow-width) var(--page-glow-height) at 50% 45%,
      var(--page-glow),
      transparent 70%
    ),
    radial-gradient(var(--lattice-ink) var(--lattice-dot), transparent var(--lattice-dot));
  background-repeat: no-repeat, repeat;
  background-size: auto, var(--lattice-pitch) var(--lattice-pitch);
  color: var(--color-ink);
  font-family: var(--font-sans);
  font-size: var(--text-body);
  line-height: var(--leading-body);
  letter-spacing: var(--tracking-body);
}

/* --- the card ------------------------------------------------------------ */

/* Centred with `margin: auto` on the flex item rather than `align-items: center` on the page: when
   a card outgrows the viewport — the extreme applications fixture does — centred alignment pushes
   its top above the scroll origin and makes it unreachable, while auto margins collapse to zero
   and leave the whole card scrollable. */
.card {
  box-sizing: border-box;
  width: 100%;
  max-width: var(--card-width);
  margin: auto;
  padding: var(--space-7) var(--space-6);
  background: var(--color-card);
  border: var(--hairline) solid var(--color-rule);
  border-top: var(--accent-rule) solid var(--color-accent);
  border-radius: var(--radius-card);
}

/* The brand lockup: a mark beside the wordmark. Every screen carries it, because familiarity is
   what makes an impersonated sign-in page recognisable as not ours. The mark is inline SVG in the
   markup rather than an icon set or a font: the book forbids anything third-party in the request
   path of a password, and a mark injected by script would vanish on the no-JS path the book
   requires every screen to keep working on. */
.brand {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0 0 var(--space-5);
  font-size: var(--text-body);
  font-weight: var(--weight-heading);
  letter-spacing: -0.01em;
  color: var(--color-ink);
}

.brand-mark {
  flex: none;
  width: var(--mark-size);
  height: var(--mark-size);
  color: var(--color-accent);
}

.brand-mark svg {
  display: block;
  width: 100%;
  height: 100%;
}

.heading {
  margin: 0;
  font-size: var(--text-heading);
  font-weight: var(--weight-heading);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-heading);
}

.destination,
.lead {
  margin: var(--space-2) 0 0;
  font-size: var(--text-lead);
  color: var(--color-ink-2);
}

.destination strong {
  font-weight: var(--weight-semibold);
  color: var(--color-ink);
}

.identity {
  margin: var(--space-2) 0 0;
  font-size: var(--text-sm);
  color: var(--color-muted);
}

.identity .identity-name {
  color: var(--color-ink-2);
  font-weight: var(--weight-medium);
}

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

/* The glyph exists because the book forbids state carried by colour ALONE. A sentence satisfies
   that on its own; a glyph beside it survives greyscale and colour blindness too, which colour
   plus sentence does not. It is decoration only if it repeats what the colour already said, and
   here it does not. */
.message {
  display: flex;
  gap: var(--space-3);
  margin: var(--space-5) 0 0;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-field);
  font-size: var(--text-body);
}

.message-glyph {
  flex: none;
  width: var(--glyph-size);
  height: var(--glyph-size);
  margin-top: var(--space-1);
}

.message-glyph svg {
  display: block;
  width: 100%;
  height: 100%;
}

.message p {
  margin: 0;
}

.message p + p {
  margin-top: var(--space-1);
  color: var(--color-ink-2);
}

.message-bad {
  background: var(--color-danger-soft);
  color: var(--color-danger);
}

.message-good {
  background: var(--color-ok-soft);
  color: var(--color-ok);
}

.message-plain {
  background: var(--color-accent-soft);
  color: var(--color-ink-2);
}

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

.fields {
  margin: var(--space-6) 0 0;
}

.field + .field {
  margin-top: var(--space-4);
}

.field label {
  display: block;
  margin-bottom: var(--space-2);
  font-size: var(--text-label);
  font-weight: var(--weight-medium);
  color: var(--color-ink-2);
}

/* The reveal sits inside the control, so the field keeps one row rather than growing a checkbox
   line beneath it. It is HIDDEN in the markup and shown by script: without scripting a button
   that does nothing is broken, while an absent one is merely absent, which is the degradation the
   book asks for. */
.field-control {
  position: relative;
}

.reveal {
  position: absolute;
  top: 0;
  right: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--control-height);
  height: var(--control-height);
  padding: 0;
  color: var(--color-muted);
  background: none;
  border: 0;
  cursor: pointer;
}

.reveal:hover {
  color: var(--color-ink-2);
}

.reveal svg {
  display: block;
  width: var(--glyph-size);
  height: var(--glyph-size);
}


.field-control input {
  padding-right: var(--control-height);
}

.field input {
  box-sizing: border-box;
  width: 100%;
  padding: var(--space-3);
  background: var(--color-field);
  color: var(--color-ink);
  font-family: var(--font-sans);
  font-size: var(--text-value);
  border: var(--hairline) solid var(--color-rule-strong);
  border-radius: var(--radius-field);
}

.field input:focus,
.card a:focus,
.button:focus {
  outline: var(--hairline) solid var(--color-focus);
  box-shadow: 0 0 0 var(--focus-halo) var(--color-accent-soft);
}

.field-error {
  margin: var(--space-2) 0 0;
  font-size: var(--text-sm);
  color: var(--color-danger);
}

/* The refusal is a live region that is always in the document and usually empty, rather than an
   element toggled with hidden: a screen reader announces text that arrives in a region it is
   already watching, and may miss an element that appears from nowhere. */
.field-error:empty {
  display: none;
}

.field-invalid input {
  border-color: var(--color-danger);
}

.field input:disabled {
  background: var(--color-field-disabled);
  color: var(--color-muted);
}

.checkbox {
  margin: var(--space-3) 0 0;
  font-size: var(--text-sm);
  color: var(--color-ink-2);
}

/* --- actions ------------------------------------------------------------- */

/* Also worn by an anchor: on the signed-out screen the primary action is a link, not a form
   submission, and it has to look identical. Hence the centring and the removed underline, which a
   button would not need. */
.button {
  display: block;
  box-sizing: border-box;
  width: 100%;
  margin: var(--space-6) 0 0;
  padding: var(--space-3);
  text-align: center;
  text-decoration: none;
  background: var(--color-accent);
  color: var(--color-accent-ink);
  font-family: var(--font-sans);
  font-size: var(--text-value);
  font-weight: var(--weight-medium);
  border: 0;
  border-radius: var(--radius-field);
  cursor: pointer;
}

.button:hover {
  background: var(--color-accent-hover);
}

.button[aria-disabled="true"] {
  opacity: 0.7;
  cursor: default;
}

.footer {
  margin: var(--space-5) 0 0;
  padding-top: var(--space-5);
  border-top: var(--hairline) solid var(--color-rule);
  font-size: var(--text-body);
  text-align: center;
}

/* A footer action is sometimes a link and sometimes a submission — signing out changes something,
   so it cannot be a link — and the two have to be indistinguishable to a reader. */
.footer a,
.footer .link-button {
  color: var(--color-accent);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.footer a:hover,
.footer .link-button:hover {
  color: var(--color-accent-hover);
}

/* A sentence that still has to wrap breaks into even lines rather than orphaning its last word. */
.lead,
.destination,
.nothing {
  text-wrap: balance;
}

/* --- the application list ------------------------------------------------ */

.applications {
  margin: var(--space-6) 0 0;
  padding: 0;
  list-style: none;
}

.applications li + li {
  margin-top: var(--space-2);
}

.applications a {
  display: block;
  padding: var(--space-3) var(--space-4);
  border: var(--hairline) solid var(--color-rule);
  border-radius: var(--radius-field);
  color: inherit;
  text-decoration: none;
}

.applications a:hover {
  border-color: var(--color-rule-strong);
  background: var(--color-accent-soft);
}

/* A monogram rather than a logo: it is derived from the application's own name, so it needs no
   column, no upload, no storage and no artwork, and it cannot go stale when an application is
   renamed. The tile takes its colours from the existing accent pair; a categorical palette would
   be colours the book does not have. Rows are told apart by their letters, which is enough at the
   five applications this list will ever hold. */
.applications a {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.application-monogram {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--monogram-size);
  height: var(--monogram-size);
  background: var(--color-accent-soft);
  color: var(--color-accent);
  border-radius: var(--radius-field);
  font-size: var(--text-sm);
  font-weight: var(--weight-heading);
  letter-spacing: 0.02em;
}

.application-text {
  min-width: 0;
  flex: 1;
}

/* The row leaves the service: it opens the application's own address rather than another page
   here. The arrow says so before the click, which the book's own decision about where rows lead
   makes worth saying. */
.application-leaves {
  flex: none;
  width: var(--glyph-size);
  height: var(--glyph-size);
  color: var(--color-muted);
}

.application-leaves svg {
  display: block;
  width: 100%;
  height: 100%;
}

.applications a:hover .application-leaves {
  color: var(--color-accent);
}

.application-name {
  display: block;
  font-size: var(--text-value);
  font-weight: var(--weight-medium);
}

.application-description {
  display: block;
  margin-top: var(--space-1);
  font-size: var(--text-sm);
  color: var(--color-muted);
}

.nothing {
  margin: var(--space-6) 0 0;
  color: var(--color-ink-2);
}

/* --- password requirements ----------------------------------------------
 * Requirements are stated before they are needed and verified as they are met, so a refused
 * submit becomes the exception instead of the routine. Three appearances: pending, met, and
 * unmet — and unmet is reached ONLY after a submit was refused, because turning a requirement red
 * while somebody is still typing scolds them for a password they have not finished writing.
 */

.requirements {
  margin: var(--space-3) 0 0;
  padding: 0;
  list-style: none;
}

.requirement {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-2);
  font-size: var(--text-sm);
  line-height: var(--leading-body);
  color: var(--color-muted);
}

.requirement-glyph {
  flex: none;
  width: var(--glyph-size);
  height: var(--glyph-size);
  color: var(--color-rule-strong);
}

.requirement-glyph svg {
  display: block;
  width: 100%;
  height: 100%;
}

.requirement-met,
.requirement-met .requirement-glyph {
  color: var(--color-ok);
}

.requirement-unmet,
.requirement-unmet .requirement-glyph {
  color: var(--color-danger);
}

/* --- a button that reads as a link ---------------------------------------
 * Asking for another email is a request to the server, so it has to be a button for the keyboard
 * and for a screen reader, while sitting inside a sentence where the eye expects a link.
 */

.link-button {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: var(--color-accent);
  text-decoration: underline;
  cursor: pointer;
}

.link-button[aria-disabled="true"] {
  color: var(--color-muted);
  text-decoration: none;
  cursor: default;
}

.resend {
  margin: var(--space-5) 0 0;
  font-size: var(--text-sm);
  color: var(--color-ink-2);
}

.resend:empty {
  display: none;
}

/* --- small screens -------------------------------------------------------
 * The book: below 420px the card stops being a card. It loses its side borders
 * and radius and becomes the page, keeping only the accent rule at the top.
 * Touch targets and the 16px value text do not shrink.
 */

@media (max-width: 420px) {
  .screen {
    padding: 0;
    background-image: none;
  }

  /* No longer centred: at this width the card IS the page, so it starts at the top. The auto
     bottom margin keeps it at its natural height instead of stretching to fill the flex line. */
  .card {
    max-width: none;
    margin: 0 0 auto;
    padding: var(--space-6) var(--space-4);
    border-left: 0;
    border-right: 0;
    border-bottom: 0;
    border-radius: 0;
  }
}

/* --- more contrast -------------------------------------------------------
 * A reader who asks for more contrast is asking for the content, not the field. Both background
 * layers are dropped whole rather than dimmed, because neither of them says anything.
 */

@media (prefers-contrast: more) {
  .screen {
    background-image: none;
  }
}

/* The address inside a lead: the ink weight of a destination name, and free to break inside
   itself, because an address has no spaces to break at. */
.lead strong {
  font-weight: var(--weight-semibold);
  color: var(--color-ink);
  overflow-wrap: anywhere;
}

/* The sign-in code: six cells over one input. The cells exist only once a script has marked the
   box enhanced; until then the input is the ordinary field of the layer, and it stays the form's
   only control either way — the cells are a picture of its value. */
.code {
  position: relative;
}

.code-cells {
  display: none;
  grid-template-columns: repeat(6, 1fr);
  gap: var(--space-2);
}

.code[data-enhanced] .code-cells {
  display: grid;
}

.code-cell {
  box-sizing: border-box;
  height: var(--control-height);
  display: grid;
  place-items: center;
  background: var(--color-field);
  color: var(--color-ink);
  font-family: var(--font-mono);
  font-size: var(--text-code);
  border: var(--hairline) solid var(--color-rule-strong);
  border-radius: var(--radius-field);
}

/* The cell the caret is in wears the field's own focus ring, so focus looks the same here as on
   every other field of the layer. */
.code-cell[data-active] {
  outline: var(--hairline) solid var(--color-focus);
  box-shadow: 0 0 0 var(--focus-halo) var(--color-accent-soft);
}

.field-invalid .code-cell {
  border-color: var(--color-danger);
}

.code[data-enhanced] input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
}

/* Two routes in one footer, each a form: they sit side by side and wrap when the card narrows. */
.footer-routes {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2) var(--space-5);
}

.footer-routes form {
  margin: 0;
}
