/* ==========================================================================
   PALACE INDEX — the sign-in page

   THIS PAGE IS NOT A SECOND DESIGN. It is the first screen of the same
   product, and the whole of its art direction is quoted from app.css:

     · the paper and its 86px architectural grid          (app.css  body)
     · the top bar — gradient, edge shadow, and the four-colour rule under
       it — reproduced here as a letterhead band          (app.css  .topbar,
                                                           .topbar::after)
     · the monogram plate: obsidian, 11/36 corner, bronze hairline, double
       ring, Baskerville H                                (app.css  .brand-mark)
     · the page head: 4px three-colour bar, a display title, a muted note
       and a --line-strong datum under it                 (app.css  .page-head)
     · fields that are --surface boxes with a --line-strong edge, and a focus
       ring drawn INSIDE that edge so nothing moves       (app.css  .filters
                                                           .search, edit.css
                                                           .fv-in)
     · one primary button in walnut-black with the studio's asymmetric
       corner pair                                        (app.css  .btn,
                                                           .btn.primary)
     · the two switches, identical to the pair in the app's header
                                                          (app.css  .lang-toggle,
                                                           .theme-toggle)

   Signing in should therefore read as the catalogue arriving under a bar
   that was already there, not as a second product opening.

   ── THE TOKEN CONTRACT ────────────────────────────────────────────────────
   Every custom property in the two :root blocks below is a COPY of a value
   in public/assets/css/app.css, and each one names the app.css token it was
   copied from. The copy exists because this page cannot read the original:

     · app.css is not linked here. index.html appends it from an inline
       bootstrap (so that ?theme= can swap it), and login.html has no such
       bootstrap and must not grow one — the sheet would restyle this page.
     · @import is not an option for the same reason, and because it is a
       second network request on a page that is required to work offline.

   SO THE TWO FILES MUST BE KEPT IN STEP BY HAND. If a value in app.css's
   PALACE INDEX :root block or its :root[data-theme="dark"] twin changes,
   change it here too. A drift is not a bug that shows up in a test — it
   shows up as the sign-in page and the catalogue looking like two different
   products, which is exactly the fault this round of work was opened to fix.
   The app.css line numbers are not quoted, deliberately: they move. The
   token names do not.

   NO NETWORK. No web font, no CDN, no external image, no @import. Everything
   on this page is a letter, a line, a colour, or a gradient.

   NO @media (prefers-color-scheme: dark). Dark here is a stored choice,
   applied as data-theme="dark" on <html> by the bootstrap in login.html.
   ========================================================================== */

:root {
  color-scheme: light;

  /* ---- copied from app.css  :root  (PALACE INDEX, light) ---------------- */
  --lg-paper:        #efeeea;              /* --paper                        */
  --lg-surface:      #fbfaf7;              /* --surface                      */
  --lg-surface-2:    #f1f1ed;              /* --surface-2                    */
  --lg-ink:          #171a1b;              /* --ink                          */
  --lg-muted:        #555f63;              /* --muted                        */
  --lg-faint:        #646d71;              /* --faint                        */
  --lg-line:         #d7d6d1;              /* --line                         */
  --lg-line-soft:    #e8e7e2;              /* --line-soft                    */
  --lg-line-strong:  #7f8789;              /* --line-strong                  */
  --lg-head:         #1d2326;              /* --head       (paints buttons)  */
  --lg-head-soft:    #30393d;              /* --head-soft  (the same, hover) */
  --lg-head-ink:     #15191a;              /* --head-ink                     */
  --lg-on-head:      #fbfcfa;              /* --on-head                      */
  --lg-head-edge:    rgba(20, 25, 27, .12);/* --head-edge                    */
  --lg-accent:       #285d7c;              /* --accent                       */
  --lg-accent-ink:   #245570;              /* --accent-ink (accent, for type)*/
  --lg-accent-line:  #9ab2c0;              /* --accent-line                  */
  --lg-accent-soft:  #e5edf1;              /* --accent-soft                  */
  --lg-bronze:       #927a5b;              /* --bronze                       */
  --lg-bronze-line:  rgba(146, 122, 91, .46); /* --bronze-line               */
  --lg-focus:        #1c638c;              /* --focus                        */
  --lg-tap:          rgba(40, 93, 124, .14); /* --tap                        */
  --lg-mark-bg:      #1d2326;              /* --mark-bg                      */
  --lg-mark-ink:     #f8f8f5;              /* --mark-ink                     */
  --lg-bad-bg:       #f8e9e7;              /* --bad-bg                       */
  --lg-bad-ink:      #94332f;              /* --bad-ink                      */
  --lg-bad-line:     #e4c5c1;              /* --bad-line                     */
  --lg-radius:       3px;                  /* --radius                       */
  --lg-architectural: rgba(27, 32, 34, .075); /* --architectural             */
  --lg-page-grid:                          /* --page-grid                    */
    linear-gradient(90deg, transparent calc(100% - 1px), var(--lg-architectural) 100%);
  --lg-topbar-bg:                          /* --topbar-bg                    */
    linear-gradient(180deg, rgba(255, 255, 253, .98), rgba(244, 243, 239, .98));
  --lg-topbar-shadow: 0 14px 40px rgba(26, 31, 33, .07); /* --topbar-shadow  */
  --lg-shadow:                             /* --shadow                       */
    0 1px 0 rgba(255, 255, 255, .82) inset,
    0 12px 36px rgba(29, 35, 38, .055);
  /* --shadow with its inset highlight taken off. The highlight is a line of
     white along the top edge and it belongs on a pale card; on the one
     walnut-black control on the page it reads as a chrome bevel. What is
     left is the ambient half, which is the half that says the button is
     resting on the paper. */
  --lg-lift: 0 12px 36px rgba(29, 35, 38, .055);

  /* Both of these are app.css's --sans and --serif, which in a Latin
     document are deliberately the same stack. --serif is what .page-head h1
     is set in, and it is redefined for Arabic further down exactly as
     app.css redefines it. */
  --lg-sans:  'Avenir Next', 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
  --lg-serif: 'Avenir Next', 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
  --lg-mono:  ui-monospace, Menlo, Consolas, 'DejaVu Sans Mono', monospace;
  /* app.css --serif-mark, and it has its own stack for one reason: --serif
     becomes an Arabic face when the document flips, and the monogram is a
     Latin capital in every language. This must never be folded into --serif. */
  --lg-serif-mark: 'Baskerville', 'Iowan Old Style', Georgia, 'Times New Roman', serif;

  /* ---- this page's own measurements ------------------------------------- */
  /* --lg-gutter tracks app.css's --gutter at the same breakpoints, so the
     sheet margin is the one the catalogue uses. */
  --lg-gutter: 38px;
  /* The step from the gutter to the text column: app.css .page-head's
     padding-inline start, which is what leaves room for the 4px bar. */
  --lg-indent: 28px;
  /* The letterhead band. Measured on the running app, .topbar is 78px on a
     desktop and 112px on a phone (where it also carries the tab strip). The
     door has no tabs, so it takes one step above the desktop bar and no more:
     the plate has to land in as nearly the same place as it can, because the
     bar is what the eye tracks across the sign-in. */
  --lg-band: 90px;
  --lg-rule: 4px;                          /* app.css .topbar::after height  */
  /* app.css --mark-size is 36px in the header and 29px on a phone. The door
     takes one step up from the header; everything about the plate other than
     its size is derived from this number, as it is in app.css. */
  --lg-mark-size: 42px;
  --lg-col: 27rem;                         /* the credential column          */

  /* Physical insets resolved once, here, so that every rule downstream can
     use logical properties. env(safe-area-inset-left) is the LEFT of the
     device whichever way the document reads — the notch does not flip — so
     the two are swapped by hand under [dir='rtl'] and nowhere else. */
  --lg-edge-start: max(var(--lg-gutter), env(safe-area-inset-left, 0px));
  --lg-edge-end:   max(var(--lg-gutter), env(safe-area-inset-right, 0px));
}

/* ---- copied from app.css  :root[data-theme="dark"]  (PALACE INDEX) ------ */
:root[data-theme='dark'] {
  color-scheme: dark;

  --lg-paper:        #101416;              /* --paper                        */
  --lg-surface:      #191e20;              /* --surface                      */
  --lg-surface-2:    #22282b;              /* --surface-2                    */
  --lg-ink:          #f0f1ed;              /* --ink                          */
  --lg-muted:        #b2b8b8;              /* --muted                        */
  --lg-faint:        #949d9f;              /* --faint                        */
  --lg-line:         #333a3d;              /* --line                         */
  --lg-line-soft:    #272e31;              /* --line-soft                    */
  --lg-line-strong:  #677477;              /* --line-strong                  */
  --lg-head:         #315f79;              /* --head                         */
  --lg-head-soft:    #3c7392;              /* --head-soft                    */
  --lg-head-ink:     #f7f8f4;              /* --head-ink                     */
  --lg-on-head:      #ffffff;              /* --on-head                      */
  --lg-head-edge:    rgba(0, 0, 0, .64);   /* --head-edge                    */
  --lg-accent:       #77acca;              /* --accent                       */
  --lg-accent-ink:   #8fbed8;              /* --accent-ink                   */
  --lg-accent-line:  #4d758b;              /* --accent-line                  */
  --lg-accent-soft:  #1b2d37;              /* --accent-soft                  */
  --lg-bronze:       #c1a77f;              /* --bronze                       */
  --lg-bronze-line:  rgba(193, 167, 127, .45); /* --bronze-line              */
  --lg-focus:        #93c5df;              /* --focus                        */
  --lg-tap:          rgba(119, 172, 202, .18); /* --tap                      */
  /* The plate inverts after dark in the app — a pale disc with a dark
     letter — and it inverts here for the same reason. */
  --lg-mark-bg:      #d8e2e6;              /* --mark-bg                      */
  --lg-mark-ink:     #151b1e;              /* --mark-ink                     */
  --lg-bad-bg:       #34201f;              /* --bad-bg                       */
  --lg-bad-ink:      #f2a19b;              /* --bad-ink                      */
  --lg-bad-line:     #603a37;              /* --bad-line                     */
  --lg-architectural: rgba(232, 238, 239, .04); /* --architectural           */
  --lg-page-grid:                          /* --page-grid                    */
    linear-gradient(90deg, transparent calc(100% - 1px), var(--lg-architectural) 100%);
  --lg-topbar-bg:                          /* --topbar-bg                    */
    linear-gradient(180deg, rgba(29, 35, 38, .98), rgba(17, 22, 24, .98));
  --lg-topbar-shadow: 0 16px 42px rgba(0, 0, 0, .34); /* --topbar-shadow     */
  --lg-shadow:                             /* --shadow                       */
    0 1px 0 rgba(255, 255, 255, .035) inset,
    0 12px 28px rgba(0, 0, 0, .24);
  --lg-lift: 0 12px 28px rgba(0, 0, 0, .24);
}

/* Arabic wants a different family and more leading, and the display face
   becomes a naskh rather than staying a sans. Both stacks are app.css's
   html[dir="rtl"] block, copied. --lg-serif-mark is deliberately absent:
   the monogram must not change shape when the language does. */
html[dir='rtl'] {
  --lg-sans:  'Segoe UI', Tahoma, 'Noto Sans Arabic', 'Dubai', 'Geeza Pro', Arial, sans-serif;
  --lg-serif: 'Amiri', 'Traditional Arabic', 'Noto Naskh Arabic', Georgia, serif;

  --lg-edge-start: max(var(--lg-gutter), env(safe-area-inset-right, 0px));
  --lg-edge-end:   max(var(--lg-gutter), env(safe-area-inset-left, 0px));
}

/* ================================================================= base === */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  min-width: 0;
  background: var(--lg-paper);
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

/* The ground is the catalogue's own paper, with the catalogue's own faint
   vertical grid on it — app.css sets exactly this pair on body. */
.lg-body {
  position: relative;
  isolation: isolate;
  min-height: 100vh;
  min-height: 100svh;
  margin: 0;
  /* Zero, on purpose: the band and the foot run to the edges of the glass,
     and every other block carries its own inset. */
  padding: 0;
  color: var(--lg-ink);
  background-color: var(--lg-paper);
  background-image: var(--lg-page-grid);
  background-size: 86px 86px;
  background-position: center top;
  font-family: var(--lg-sans);
  font-size: 15px;
  line-height: 1.62;
  -webkit-tap-highlight-color: var(--lg-tap);
  overflow-wrap: break-word;
}

html[dir='rtl'] .lg-body { line-height: 1.8; }

/* The architectural ellipse. It is app.css's .page-head::after — the one
   ornament the catalogue allows itself — enlarged for a page that has a
   whole wall to itself. Three concentric hairlines at 7.5% of the ink: it
   is nearly not there, which is the point. Drawn rather than fetched,
   because there is no image this page is allowed to load.

   position: fixed keeps it out of the document's scrollable overflow, and
   the outline and box-shadow rings never contributed to it in the first
   place, so it cannot widen the page. */
.lg-body::after {
  content: '';
  position: fixed;
  z-index: 0;
  inset-block-start: 27%;
  inset-inline-end: 7vw;
  /* app.css draws it at 220 × 112 with rings at 15 and 30/31 — a ratio of
     about .14 of the width. Enlarged for a page with a wall to itself, at
     the same ratio, so it stays the same drawing. */
  width: min(26vw, 340px);
  height: min(13vw, 173px);
  border: 1px solid var(--lg-architectural);
  border-radius: 50%;
  outline: 1px solid var(--lg-architectural);
  outline-offset: 23px;
  box-shadow:
    0 0 0 46px transparent,
    0 0 0 47px var(--lg-architectural);
  transform: rotate(-7deg);
  pointer-events: none;
}

/* A rotation has no logical form, so the mirror is written by hand. */
html[dir='rtl'] .lg-body::after { transform: rotate(7deg); }

/* ================================================================ frame === */

/*
   One column, full width, seven rows. Rows 2 and 6 are the only elastic ones
   and they are what fills a tall phone: whatever height is left over after
   the band, the head, the form and the foot is divided between the air above
   the title and the air above the foot, roughly 0.85 to 1.15. Nothing is
   centred by accident and nothing is left hanging in the middle — the band
   is against the top of the glass, the foot is against the bottom of it.
*/
.lg-card {
  position: relative;
  z-index: 1;
  isolation: isolate;
  width: 100%;
  min-height: 100vh;
  min-height: 100svh;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows:
    calc(var(--lg-band) + env(safe-area-inset-top, 0px))  /* 1  letterhead   */
    minmax(24px, .9fr)                                    /* 2  air          */
    auto                                                  /* 3  title        */
    auto                                                  /* 4  note + datum */
    auto                                                  /* 5  form         */
    minmax(28px, 1.1fr)                                   /* 6  air          */
    auto;                                                 /* 7  foot         */
  color: var(--lg-ink);
}

/* THE LETTERHEAD BAND — app.css's .topbar, reproduced.

   Same gradient, same 1px edge over the same drop shadow, same four-colour
   rule along its foot in the same proportions (obsidian, sapphire, bronze,
   then the long grey run). It reaches into the safe area at the top exactly
   as .topbar does, so the Dynamic Island sits on the band and not on paper.

   It is painted by the card rather than by .lg-mark so that the monogram
   element contains the monogram and nothing else — a band with a mark at its
   inline start is a different set of pixels in Arabic, and the plate is not
   allowed to be. */
.lg-card::before {
  content: '';
  position: absolute;
  z-index: 0;
  inset-block-start: 0;
  inset-inline: 0;
  height: calc(var(--lg-band) + env(safe-area-inset-top, 0px));
  background-image:
    linear-gradient(
      90deg,
      var(--lg-head) 0 18%,
      var(--lg-accent) 18% 31%,
      var(--lg-bronze) 31% 36%,
      var(--lg-line-strong) 36% 100%
    ),
    var(--lg-topbar-bg);
  background-repeat: no-repeat, no-repeat;
  background-position: 0 100%, 0 0;
  background-size: 100% var(--lg-rule), 100% 100%;
  box-shadow: 0 1px 0 var(--lg-head-edge), var(--lg-topbar-shadow);
  pointer-events: none;
}

/* A gradient has no logical direction. app.css mirrors this exact rule with
   a 270deg twin and so does this one. */
html[dir='rtl'] .lg-card::before {
  background-image:
    linear-gradient(
      270deg,
      var(--lg-head) 0 18%,
      var(--lg-accent) 18% 31%,
      var(--lg-bronze) 31% 36%,
      var(--lg-line-strong) 36% 100%
    ),
    var(--lg-topbar-bg);
}

.lg-card > * {
  position: relative;
  z-index: 1;
}

/* ============================================================= monogram === */

/*
   THE PLATE. Every declaration here is app.css's .brand-mark: the obsidian
   ground, the bronze hairline, the 3px reveal ring closed by a 1px
   --line-strong hairline, the corner at 11/36 of the plate, the letter at
   .66 of it, and the 1px of foot padding that lifts a capital off the
   optical centre of a square.

   The size is the only thing that changed, so the corner and the letter are
   written as ratios of it rather than as numbers: the plate on the door is
   the plate in the header, enlarged, and not a second drawing of it.
*/
.lg-mark {
  grid-row: 1;
  align-self: center;
  justify-self: start;
  /* align-self: center measures the MARGIN box, so a top margin equal to the
     inset lands the plate in the middle of the visible band rather than in
     the middle of the band plus the notch. */
  margin-block-start: env(safe-area-inset-top, 0px);
  margin-inline-start: calc(var(--lg-edge-start) + var(--lg-indent));
  width: var(--lg-mark-size);
  height: var(--lg-mark-size);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--lg-mark-ink);
  background: var(--lg-mark-bg);
  border: 1px solid var(--lg-bronze-line);
  border-radius: calc(var(--lg-mark-size) * 11 / 36);
  box-shadow:
    0 0 0 3px var(--lg-surface),
    0 0 0 4px var(--lg-line-strong);
  /* The ornament in the locked markup is suppressed here, not deleted —
     see the note on ::before. */
  font-size: 0;
  line-height: 1;
  letter-spacing: 0;
  text-align: center;
  text-transform: uppercase;
  user-select: none;
}

/* settings.yaml deliberately keeps the monogram in data, but this signed-out
   page cannot read it: /data.js returns 401 before authentication. The locked
   login.html still contains the old ornament, so this one justified exception
   suppresses that glyph and supplies the studio's H in CSS. */
.lg-mark::before {
  content: 'H';
  display: block;
  padding-block-end: 1px;
  color: inherit;
  /* A Latin capital in an Arabic document is still a Latin capital.
     `direction` sits on the LETTER and not on the plate, and that placement
     is load-bearing: the plate is positioned with margin-inline-start, and a
     direction of ltr on the plate itself would resolve that margin against
     the plate rather than against the page — which parked the mark half off
     the right edge of the screen in Arabic. */
  direction: ltr;
  font: 400 calc(var(--lg-mark-size) * .66) / 1 var(--lg-serif-mark);
  letter-spacing: 0;
  text-transform: uppercase;
}

/* Where the engine can trim the line box to cap-height-to-baseline, the thing
   being centred becomes the letter itself and the centring stops depending on
   which face answered. app.css makes the same trade behind the same query. */
@supports (text-box: trim-both cap alphabetic) {
  .lg-mark {
    display: block;
    align-content: center;
    text-box: trim-both cap alphabetic;
  }

  .lg-mark::before { padding-block-end: 0; }
}

/* ============================================================= page head === */

/*
   app.css's .page-head, with the same parts in the same order: a 4px bar in
   obsidian / sapphire / bronze standing at the gutter, the title in the
   display face at the display size, the note in --muted, and a --line-strong
   datum closing the block. After sign-in the catalogue's own title appears
   in this position, at this size, against this bar.
*/
.lg-title {
  grid-row: 3;
  position: relative;
  margin: 0;
  padding-inline:
    calc(var(--lg-edge-start) + var(--lg-indent))
    max(var(--lg-edge-end), calc(100% - 46rem));
  color: var(--lg-head-ink);
  font-family: var(--lg-serif);
  font-size: clamp(38px, 5.6vw, 68px);
  font-weight: 300;
  line-height: 1.02;
  letter-spacing: -.052em;
  text-align: start;
  text-wrap: balance;
}

.lg-title::before {
  content: '';
  position: absolute;
  inset-inline-start: var(--lg-edge-start);
  inset-block: 4px 2px;
  width: 4px;
  background:
    linear-gradient(
      to bottom,
      var(--lg-head) 0 44%,
      var(--lg-accent) 44% 78%,
      var(--lg-bronze) 78% 100%
    );
}

.lg-note {
  grid-row: 4;
  position: relative;
  margin: 0;
  padding-block: 13px 30px;
  padding-inline:
    calc(var(--lg-edge-start) + var(--lg-indent))
    max(var(--lg-edge-end), calc(100% - 46rem));
  color: var(--lg-muted);
  font-size: 14px;
  text-align: start;
  text-wrap: pretty;
}

/* The datum. It runs gutter to gutter — past the text column on both sides —
   because it is the floor the head stands on rather than an underline for the
   sentence above it. */
.lg-note::after {
  content: '';
  position: absolute;
  inset-block-end: 0;
  inset-inline: var(--lg-edge-start) var(--lg-edge-end);
  height: 1px;
  background: var(--lg-line-strong);
}

/* ================================================================= form === */

.lg-form {
  grid-row: 5;
  justify-self: start;
  width: 100%;
  max-width:
    calc(var(--lg-col) + var(--lg-edge-start) + var(--lg-indent) + var(--lg-edge-end));
  margin: 0;
  padding-block-start: 32px;
  padding-inline: calc(var(--lg-edge-start) + var(--lg-indent)) var(--lg-edge-end);
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  /* One column at every width. Two credential fields side by side is what
     left the button standing under one of them with nothing beside it. */
  gap: 18px;
}

.lg-field {
  display: block;
  min-width: 0;
}

/* app.css's .tile .k — the small caps in --accent-ink that label a figure. */
.lg-label {
  display: block;
  margin-block-end: 8px;
  color: var(--lg-accent-ink);
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: .14em;
  line-height: 1.5;
  text-align: start;
  text-transform: uppercase;
}

/*
   A FIELD LOOKS LIKE A FIELD BEFORE IT IS TOUCHED, AND DOES NOT CHANGE SHAPE
   WHEN IT IS. --surface on --paper is the same step the catalogue's own
   search box makes, and the --line-strong edge around it is the same edge:
   in daylight on a factory floor the box is found by its border, not by a
   4-value difference in fill.

   Nothing about the box moves on focus. The ring is drawn one pixel INSIDE
   the border — app.css and edit.css both focus with outline-offset: -1px —
   so a focused field and an unfocused one are the same control in the same
   place, one of them lit.
*/
.lg-input {
  display: block;
  width: 100%;
  min-height: 52px;
  margin: 0;
  padding-block: 12px;
  padding-inline: 14px;
  appearance: none;
  color: var(--lg-ink);
  background: var(--lg-surface);
  border: 1px solid var(--lg-line-strong);
  border-radius: var(--lg-radius);
  caret-color: var(--lg-accent);
  font-family: var(--lg-sans);
  /* 16px or larger, always: below it iOS zooms the page on focus. */
  font-size: 16px;
  line-height: 1.4;
  /* The element carries dir="ltr" from the locked markup in every language,
     and `start` is resolved against that. No direction or unicode-bidi is set
     here — a credential is Latin and inherited RTL makes it jump while it is
     being typed. */
  text-align: start;
  transition:
    border-color 140ms ease,
    box-shadow 140ms ease;
}

.lg-input:focus {
  outline: 2px solid var(--lg-focus);
  outline-offset: -1px;
  border-color: var(--lg-focus);
}

.lg-input:disabled {
  opacity: .58;
  cursor: wait;
}

/* WebKit paints its own fill over an autofilled field; this is the only way
   to put the theme's back. */
.lg-input:-webkit-autofill,
.lg-input:-webkit-autofill:hover,
.lg-input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--lg-ink);
  caret-color: var(--lg-accent);
  box-shadow: 0 0 0 1000px var(--lg-surface) inset;
}

/* app.css's --bad-* trio. The heavier edge is on the inline start, so it is
   the left of an English refusal and the right of an Arabic one. */
.lg-error {
  margin: 0;
  padding-block: 11px;
  padding-inline: 14px;
  overflow-wrap: anywhere;
  color: var(--lg-bad-ink);
  background: var(--lg-bad-bg);
  border: 1px solid var(--lg-bad-line);
  border-inline-start: 3px solid var(--lg-bad-ink);
  border-radius: var(--lg-radius);
  font-size: 14px;
  line-height: 1.55;
  text-align: start;
}

.lg-error[hidden] { display: none; }

/* The one case where the refusal carries a command to run. A Latin command
   inside an Arabic paragraph comes out reordered and unrunnable, so it is
   isolated — this is a code sample, not a credential field. */
.lg-cmd {
  display: block;
  margin-block-start: 8px;
  padding-block: 6px;
  padding-inline: 8px;
  direction: ltr;
  unicode-bidi: isolate;
  color: var(--lg-ink);
  background: var(--lg-surface);
  border: 1px solid var(--lg-line);
  border-radius: var(--lg-radius);
  font-family: var(--lg-mono);
  font-size: 12px;
  line-height: 1.5;
  text-align: left;
  word-break: break-all;
}

/* app.css's .btn.primary: walnut-black, and the studio's corner pair — two
   square corners and two rounded ones on the diagonal, which is the shape
   every button in the catalogue is cut to. The radii are logical, so the
   diagonal turns over with the document. */
.lg-submit {
  display: block;
  width: 100%;
  min-height: 52px;
  margin-block-start: 6px;
  padding-block: 13px;
  padding-inline: 20px;
  appearance: none;
  color: var(--lg-on-head);
  background: var(--lg-head);
  border: 1px solid var(--lg-head);
  border-radius: 2px;
  border-start-end-radius: 13px;
  border-end-start-radius: 13px;
  /* The catalogue's plates rest on the paper rather than float above it, and
     so does the one control that opens it. */
  box-shadow: var(--lg-lift);
  cursor: pointer;
  font-family: var(--lg-sans);
  font-size: 14px;
  font-weight: 650;
  letter-spacing: .03em;
  line-height: 1.4;
  transition:
    background-color 140ms ease,
    border-color 140ms ease,
    opacity 140ms ease;
}

.lg-submit:focus-visible {
  outline: 2px solid var(--lg-focus);
  outline-offset: 3px;
}

.lg-submit:active { opacity: .75; }

.lg-submit:disabled {
  opacity: .58;
  cursor: wait;
}

/* ================================================================= foot === */

/*
   The page has a floor. The rule runs gutter to gutter, the two switches sit
   under it at the end of the line, and the whole block is against the bottom
   of the glass with the home indicator's clearance below it — app.css's
   .sitefoot, doing the job it does there.
*/
.lg-tools {
  grid-row: 7;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
  padding-block: 20px calc(20px + env(safe-area-inset-bottom, 0px));
  padding-inline: calc(var(--lg-edge-start) + var(--lg-indent)) var(--lg-edge-end);
}

.lg-tools::before {
  content: '';
  position: absolute;
  inset-block-start: 0;
  inset-inline: var(--lg-edge-start) var(--lg-edge-end);
  height: 1px;
  background: var(--lg-line);
}

/* app.css's .lang-toggle / .theme-toggle, which are one control in two
   widths: same box, same hairline, same fill, same 44px. */
.lg-tool {
  min-width: 44px;
  min-height: 44px;
  padding-block: 7px;
  padding-inline: 14px;
  appearance: none;
  color: var(--lg-accent-ink);
  background: var(--lg-surface);
  border: 1px solid var(--lg-line-strong);
  border-radius: var(--lg-radius);
  cursor: pointer;
  font-family: var(--lg-sans);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .1em;
  line-height: 1.2;
  text-transform: uppercase;
  transition:
    color 140ms ease,
    background-color 140ms ease,
    border-color 140ms ease;
}

.lg-tool:focus-visible {
  outline: 2px solid var(--lg-focus);
  outline-offset: 2px;
}

.lg-tool:active { opacity: .75; }

/* The language button is the one control whose label is in the OTHER
   language, so its tracking cannot be decided by the document's direction.
   login.js writes lang="ar" on it while the page is English; .1em of
   tracking pulls the joins of an Arabic word apart, so it comes off
   whenever the word inside is Arabic, in either direction. */
.lg-tool:lang(ar) { letter-spacing: 0; }

#lg-theme {
  width: 48px;
  padding-inline: 0;
  /* The sun and the moon are drawn by whichever face has them; the Latin
     stack is the one that does, and it is the same stack as the monogram's
     so the two glyphs on the page come from one family. */
  font-family: var(--lg-serif-mark);
  font-size: 17px;
  letter-spacing: 0;
}

/* ================================================================== RTL === */

/* Arabic is cursive: the tracking that makes a Latin small-caps label look
   considered, and the negative tracking that makes a display line sit tight,
   both read as a fault in Arabic. app.css drops both on every label carrying
   a translated string, and so does this. */
html[dir='rtl'] .lg-title,
html[dir='rtl'] .lg-note,
html[dir='rtl'] .lg-label,
html[dir='rtl'] .lg-submit,
html[dir='rtl'] .lg-tool {
  letter-spacing: 0;
}

html[dir='rtl'] .lg-label {
  /* 9.5px of Arabic is unreadable, and there is no case for uppercase to
     act on. The label steps up to a size the script can carry. */
  font-size: 12px;
  text-transform: none;
}

/* ========================================================== responsive === */

/* The three widths app.css itself steps at, with app.css's own --gutter
   at each one. */

@media (max-width: 1100px) {
  :root { --lg-gutter: 24px; }
}

@media (max-width: 767px) {
  :root {
    --lg-gutter: 18px;
    --lg-indent: 18px;
    --lg-band: 88px;
    /* app.css takes the header rule to 3px here. */
    --lg-rule: 3px;
    --lg-mark-size: 40px;
    --lg-col: 100%;
  }

  .lg-body::after {
    inset-block-start: 30%;
    outline-offset: 20px;
    box-shadow:
      0 0 0 40px transparent,
      0 0 0 41px var(--lg-architectural);
  }

  .lg-form { padding-block-start: 26px; }
}

/*
   THE PHONE, WHICH IS THE DEVICE THAT MATTERS.

   It is not the desktop narrowed. The band comes down, the grid closes to the
   catalogue's own 64px, the title drops to the size the catalogue uses on a
   phone, the credential column becomes the width of the glass, and the two
   elastic rows above the title and above the foot take up whatever is left so
   that the page ends at the bottom of the screen instead of two thirds of the
   way down it. Everything a thumb has to reach — both fields, the button,
   both switches — is at least 44px and in the lower two thirds.
*/
@media (max-width: 480px) {
  :root {
    --lg-gutter: 15px;
    --lg-indent: 15px;
    --lg-band: 82px;
    --lg-mark-size: 38px;
  }

  .lg-body {
    font-size: 14.5px;
    background-size: 64px 64px;
  }

  /* On the glass the ornament runs off the edge rather than sitting inside
     it, exactly as the catalogue's does on a phone: what is left on screen
     is an arc, not a ring, and an arc does not compete with the title. */
  .lg-body::after {
    inset-block-start: 21%;
    inset-inline-end: -14vw;
    width: 54vw;
    height: 27vw;
    outline-offset: 14px;
    box-shadow:
      0 0 0 28px transparent,
      0 0 0 29px var(--lg-architectural);
  }

  .lg-card {
    grid-template-rows:
      calc(var(--lg-band) + env(safe-area-inset-top, 0px))
      minmax(18px, .95fr)
      auto
      auto
      auto
      minmax(22px, 1.05fr)
      auto;
  }

  .lg-note { padding-block: 11px 26px; }

  .lg-form {
    padding-block-start: 26px;
    gap: 16px;
  }

  .lg-tools { padding-block: 16px calc(16px + env(safe-area-inset-bottom, 0px)); }
}

/*
   A SHORT VIEWPORT, AND THE THRESHOLD IS THE POINT. An iPhone 14 in Safari
   gives the page 664 CSS pixels of height in portrait — that is the owner's
   normal case, not an emergency, and a rule that fires at 700 turns his
   everyday screen into the compressed one. This starts at 560, which is
   below every phone in portrait and above the 390 a phone gives in
   landscape.

   Below it the elastic rows are already at their minimum, so the fixed parts
   give way instead: the band loses a third of its height, the head loses its
   air, and the page still ends at the bottom of the glass with nothing cut
   off and every tap target still at 44px.
*/
@media (max-height: 560px) and (max-width: 880px) {
  :root {
    --lg-band: 66px;
    --lg-mark-size: 34px;
  }

  .lg-title { font-size: clamp(28px, 7vw, 34px); }

  .lg-note {
    padding-block: 8px 16px;
    line-height: 1.45;
  }

  html[dir='rtl'] .lg-note { line-height: 1.6; }

  .lg-form {
    padding-block-start: 18px;
    gap: 12px;
  }

  .lg-input,
  .lg-submit { min-height: 46px; }

  .lg-input { padding-block: 9px; }

  .lg-submit {
    margin-block-start: 2px;
    padding-block: 10px;
  }

  .lg-label { margin-block-end: 5px; }

  .lg-tools { padding-block: 12px calc(12px + env(safe-area-inset-bottom, 0px)); }

  .lg-body::after { display: none; }
}

/* Shorter still — a phone on its side, or a browser window dragged down to a
   strip. The page stops insisting on filling the glass and is simply allowed
   to scroll, which is the honest answer once there is no height to compose
   with. */
@media (max-height: 430px) {
  :root { --lg-band: 56px; --lg-mark-size: 30px; }

  .lg-card { min-height: 0; }

  .lg-body::after { display: none; }
}

/* ============================================================ pointers === */

@media (hover: hover) and (pointer: fine) {
  .lg-submit:hover {
    background: var(--lg-head-soft);
    border-color: var(--lg-head-soft);
  }

  .lg-tool:hover {
    color: var(--lg-accent-ink);
    background: var(--lg-accent-soft);
    border-color: var(--lg-accent-line);
  }
}

@media (prefers-reduced-motion: reduce) {
  .lg-input,
  .lg-submit,
  .lg-tool {
    transition: none;
  }
}

@media (forced-colors: active) {
  .lg-input,
  .lg-submit,
  .lg-tool,
  .lg-error,
  .lg-cmd {
    border: 1px solid CanvasText;
  }

  .lg-mark {
    color: Canvas;
    background: CanvasText;
    box-shadow: none;
  }

  .lg-input:focus,
  .lg-submit:focus-visible,
  .lg-tool:focus-visible {
    outline: 2px solid Highlight;
  }

  .lg-title::before,
  .lg-note::after,
  .lg-tools::before {
    background: CanvasText;
    forced-color-adjust: none;
  }
}
