/* =====================================================================
   THE SHELL - sign in, and the home screen.

   PLACEMENT ONLY, the way apps/game/public/place.css is placement only for the 34
   windows. Every box on these two screens is already a design-system
   component - `.win`, `.band`, `.rows`, `.tile`, `.well`, `.field`,
   `.tabs`, `.btn`, `.doll-box` - and this sheet says where they sit and
   how big the stage is. It invents no face, no rim and no colour of its
   own: every value below is a token out of apps/game/public/hud-ui/design.css.

   It replaces public/auth.css (1,100 lines) and
   public/dashboard/dashboard.css, both of which drew a second window
   system beside the game's.
   ===================================================================== */

.shell {
  position: fixed;
  inset: 0;
  z-index: 30;                       /* over the canvas, under a dialog's .scrim */
  font: var(--face-weight) var(--win-size)/1.35 var(--face-ui);
  color: var(--ink);
}
.shell[hidden] { display: none; }

/* The stage: the vista, and whatever stands on it. Full viewport, no page
   scroll and no page chrome - this screen is the whole window, not a
   document in one. */
.shell__stage {
  position: absolute;
  inset: 0;
  display: grid;
  overflow: hidden;
  background: #81c9ec url("/data/art/landing/character-selection-world-v8-simple-day.0f2c0a25.webp") center 58% / cover no-repeat;
}
/* The logo and the box under it, stacked and centred as a pair; the build line is pinned to the
   foot of the screen on its own (below), so it does not pull the pair off centre. */
.shell__stage--signin { place-items: center; align-content: center; gap: .4em; padding: 1em; }
/* Four rows, each child pinned to its own: the top bar, the download strip under it, the
   vista, the verbs. Pinned rather than flowed, so the strip's row is simply empty (no height,
   no gap) while the strip is hidden and the vista keeps the stretching row either way. */
.shell__stage--home { grid-template-rows: auto auto minmax(0, 1fr) auto; }
.shell__stage--home > .shell__band { grid-row: 1; }
.shell__stage--home > .shell__world { grid-row: 2; }
.shell__stage--home > .shell__vista { grid-row: 3; }
.shell__stage--home > .shell__verbs { grid-row: 4; }

/* ------------------------------------------------------------- sign in */

/* The sign-in box is a HEADLESS window, and it is the only one. Everything about it is the
   design system's .win - the parchment, the rim, the radius - minus the title bar, because a box
   that is the whole screen has nothing to be closed to and a title that reads "Tamerland" under a
   logo that already says so. The window stack is untouched: .win--headless only skips the head, so
   nothing here is a second window implementation.
   It holds the buttons and nothing else (user, 2026-09-24: "too ugly" - the crest card was a tall
   blank slab with the logo lost in it), so it is only as wide as the longest label on one line. */
.shell__signin { width: min(25em, 100%); min-width: 0; }
.shell__signin > .win__body {
  display: grid;
  gap: .8em;
  padding: 1.2em 1.1em 1.1em;
}
/* THE LOGO stands on the vista, over the box, at title-screen size: it is the screen's picture,
   not an item in a list. The shadow lifts it off the sky the way the box's own shadow lifts the box. */
.shell__crest {
  display: block;
  width: min(26em, 100%);
  height: auto;
  filter: drop-shadow(0 .5em 1em rgba(var(--shadow-ink), .35));
  user-select: none;
}
/* Each button is the tan primary, full width, with the provider's own mark in it: Google's branding
   asks for the four-colour G unaltered, so the marks sit on a white chip rather than on the tan. The
   label never wraps: "Continue with Discord" on two lines made two buttons of different heights. */
.shell__signin [data-go] {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .55em;
  white-space: nowrap;
  font-size: 1.2em;
}
.shell__provider {
  width: 1.45em;
  height: 1.45em;
  padding: .2em;
  box-sizing: border-box;
  background: #fff;
  border-radius: 50%;
  box-shadow: 0 .06em .12em rgba(var(--shadow-ink), .3);
  flex: none;
}
/* Shut (sign-in closed, maintenance, a provider with no keys): still the tan button, only faded.
   The system's own disabled wash desaturates the tan into a grey-mauve that read as broken here,
   where the two buttons are the whole screen. */
/* A phone narrower than the longest label: the buttons take a window's own size so it still fits. */
@media (max-width: 24em) { .shell__signin [data-go] { font-size: 1em; } }
.shell__signin [data-go]:disabled { filter: none; opacity: .55; }
.shell__signin [data-err] { text-align: center; }
.shell__signin [data-err]:empty { display: none; }
/* The build number, OUTSIDE the box at the foot of the screen: it is about the client, not about
   signing in. Pale on the vista, with a shadow so the path under it cannot swallow it. */
.shell__build {
  position: absolute;
  left: 0;
  right: 0;
  bottom: .8em;
  margin: 0;
  text-align: center;
  font-size: .85em;
}
.shell__build .note-line {
  display: inline;
  color: #fff;
  opacity: .85;
  text-shadow: 0 .06em .25em rgba(var(--shadow-ink), .7);
}

/* ---------------------------------------------------------- home: band */

/* THE ACCOUNT'S SHELF, straight across the top of the stage.

   It was a plain `.band` at the window system's own 12px: the grey
   information strip a window wears UNDER its head, laid over a painted
   vista. At that weight it read as a browser toolbar somebody had left on
   top of the game. Two changes, and neither of them is a new face - both
   are material the design system already ships.

   IT IS BIGGER. A window is read at arm's length inside the world; this
   shelf is read from as far back as the vista behind it, which is the
   same distance the four sections are read from, so it takes their 14px
   --win-size rather than the 12px a window wears. One line scales all of
   it - type, pills, the tab strip, the purse, the button - because every
   box in the system is drawn in em against that number. The narrow
   breakpoint at the bottom of this sheet hands it back to 12px, where the
   screen is the size of a hand and the strip has to fit.

   IT WEARS THE WINDOW HEAD'S OWN FACE. The parchment gradient, the pale
   rim with the warm hairline just inside it and the window shadow: that
   is what .win__head and .win paint, and this shelf is the account's
   title bar, so it is drawn as one. Plain parchment, no scrollwork (user,
   2026-09-24: the knots at the ends came off). No overflow:hidden either,
   so the account menu can hang below it. */
.shell__band {
  --win-size: 14px;
  font-size: var(--win-size);
  position: relative;
  margin: .8em .8em 0;
  min-height: 3.6em;
  padding: .5em 1.4em;
  gap: .7em;
  row-gap: .5em;
  flex-wrap: wrap;
  color: var(--ink);
  border-radius: .55em;
  /* Over every section window, so the account menu drops OVER an open section rather than under
     its head: windows stack from 20 up, dialogs start at 80 (hud-ui.ts Z). */
  z-index: 70;
  background: linear-gradient(var(--parch), var(--parch) 78%, var(--parch-edge));
  box-shadow: var(--win-shadow), inset 0 0 0 3px var(--rim), inset 0 0 0 4px var(--rim-in);
}
/* Who is signed in, at the far right, and a button: it drops the account
   menu. No glyph before it; a chevron after it says it opens. */
.shell__acct { position: relative; display: inline-flex; min-width: 0; }
.shell__who {
  display: inline-flex; align-items: center; gap: .35em; min-width: 0; max-width: 22em;
  padding: .15em .3em; margin: 0; border: 0; border-radius: .4em;
  background: none; color: inherit; font: inherit; cursor: var(--cur-hand, pointer);
}
.shell__who:hover, .shell__who[aria-expanded="true"] { background: rgba(70, 30, 15, .08); }
.shell__who > .ic { width: 1em; height: 1em; color: var(--ink-mute); flex: none; }
/* The menu: the game's own row-menu card, hung under the name's right edge. */
.shell__menu { position: absolute; top: calc(100% + .4em); right: 0; width: auto; min-width: 11em; padding: .25em .4em; }
.shell__menu .item-row { grid-template-columns: 1fr; padding: .5em .6em; }
.shell__menu[hidden] { display: none; }
/* The address in the UI's sans face, not the display face: an email set in a blackletter reads as
   a name it is not (user, 2026-09-24). */
.shell__who-name {
  font: 600 1.3em/1.1 var(--face-ui);
  color: var(--ink-strong);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.shell__band .band__action { display: flex; align-items: center; gap: .6em; flex-wrap: wrap; }
/* Three cells, the outer two equal, so the tab strip sits on the SCREEN's centre line rather
   than halfway between a wide name and a narrow purse. The band's own auto margins centred it
   between its neighbours, which put the strip left of centre by half the difference. */
.shell__band { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; }
.shell__band .band__mid { margin: 0; justify-self: center; }
.shell__band .band__action { justify-self: end; }
.shell__purse { justify-self: start; display: inline-flex; font-size: 1.15em; }
/* Coin first, then the number: this purse opens the bar's left edge, so the picture leads (user,
   2026-09-24). Only here; everywhere else a chip keeps money()'s number-then-coin order. */
.shell__purse .coin { order: -1; }

/* --------------------------------------------------------- home: rank */

/* The characters, standing in a rank on the path. One row, centred, every
   card hung from a common top so every foot line lands on the same rule. */
.shell__vista {
  grid-area: 2 / 1;                  /* the middle band, between the account line and the verbs */
  display: grid;
  place-items: center;               /* the rank stands in the middle of the vista, both ways */
  overflow: auto;
  padding: 1.2em .8em 2em;
}
.shell__rank {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: .8em;
  flex-wrap: wrap;
}
.shell__card {
  width: 12em;                       /* a head has to hold a twelve-letter nickname */
  padding: 0;
  border: 0;
  font: inherit;
  color: inherit;
  text-align: center;
  cursor: var(--cur-hand, pointer);
  transition: transform 120ms ease-out;
}
.shell__card:hover { transform: translateY(-.2em); }
/* The picked one is lifted and wears the window system's own tan selection
   ring; nothing about it is a second kind of highlight. */
.shell__card.is-picked { transform: translateY(-.45em); box-shadow: 0 0 0 .18em var(--tan), 0 .5em 1.2em rgba(var(--shadow-ink), .35); }
/* The nickname is the card's TITLE, in the head, with the head's own knot of
   engraving behind it. A window's head is padded to the 1.2em rhythm of a
   panel and sets its title at 1.3em; a card is 12em wide and a nickname can be
   twelve letters, so the padding comes in and the title down, and a name that
   still does not fit is cut with an ellipsis rather than allowed to push the
   rank apart. The head KEEPS its 3em height, because .win::before draws the
   shadow the head casts on the body at exactly that depth. */
.shell__card .win__head { padding: 0 .6em; justify-content: center; }
.shell__card .win__title { font-size: 1.05em; max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
.shell__card .win__body { display: grid; gap: .35em; justify-items: center; }
/* An empty plinth has no head, so its body carries the height the doll and the
   head together carry on a card that is somebody. */
.shell__card--empty .win__body { min-height: 15.5em; align-content: center; }
.shell__plus { font-size: 3em; line-height: 1; color: var(--ink-faint); }
.shell__doll { margin-bottom: .2em; }
/* THE TAMER TICKET RIBBON. A ticket is worn by one character, so it is said on that character's card
   and nowhere else: a tan band laid across the top-right corner, the way a ribbon is pinned across
   the corner of a plaque, cut by the card's own edge on both ends. The card clips it; the picked
   card's ring is a box-shadow and is not clipped by the card's own overflow. */
.shell__card--ticket { overflow: hidden; }
.shell__ribbon {
  position: absolute;
  top: 1.35em;
  right: -2.6em;
  z-index: 2;
  width: 10em;
  padding: .12em 0;
  transform: rotate(45deg);
  background: var(--tan);
  color: var(--tan-text);
  box-shadow: 0 .1em .35em rgba(var(--shadow-ink), .35);
  font-size: .72em;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  text-align: center;
  line-height: 1.5;
  pointer-events: none;
}
.shell__meta { display: flex; align-items: center; gap: .4em; color: var(--ink-mute); font-size: .9em; }

/* -------------------------------------------------------- home: verbs */

/* The verb row at the foot of the stage: Enter world on the centre line and
   Delete at the right edge; the left cell stays empty so the primary keeps the
   centre. The same three-cell grid the band above uses, so the primary sits
   under the tab strip, and the destructive verb is as far from it as the screen
   allows. */
.shell__verbs {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 1.6em;
  padding: 0 1.6em 1.4em;
}
.shell__verbs-side { display: inline-flex; align-items: center; justify-self: start; }
.shell__verbs-side--end { justify-self: end; }

/* ------------------------------------------------------ home: sections */

/* A section, the forge and every dialog this screen raises open in the VISTA'S
   OWN CELL - the same grid area the rank stands in, so the account line above
   and the world line and the verbs below are never covered and never dimmed.
   This is not a modal: the bars behind it stay lit and stay clickable, and a
   section is left by the same tab strip that opened it.

   No wash behind it: the window stands straight on the vista. */
.shell__over {
  grid-area: 2 / 1;
  display: grid;
  place-items: center;
  gap: .8em;
  padding: .8em;
  overflow: auto;
}
.shell__over[hidden] { display: none; }
.shell__over .winset { display: flex; align-items: flex-start; gap: .8em; flex-wrap: wrap; justify-content: center; }
/* The forge is three pages side by side on a desk, not three tabs: a
   winset lays its pages out in a row here and each one keeps its own head.
   Below the fold they stack, which is what a phone gets. */
.shell__over .winset > .win { display: block; }

/* While anything stands in the over cell - a section, the forge, the account
   page - the rank, the download line and the verbs under it are gone, not
   dimmed: a plinth peering out from under the till read as a second thing to
   click. The over takes their rows as well, so a section is the whole height. */
.shell__stage--home.is-over .shell__vista,
.shell__stage--home.is-over .shell__world,
.shell__stage--home.is-over .shell__verbs { display: none; }
.shell__stage--home.is-over .shell__over { grid-area: 2 / 1 / 5 / 2; }

/* A SECTION IS THE WHOLE STAGE. Top Up, Economy, Market and Settings are
   screens, not dialogs: they fill the cell edge to edge instead of floating as
   a box of their own width in the middle of it.

   And a screen is read from further back than a window is. Every box in the
   game is drawn in em off --win-size, so ONE line here scales the whole
   section - type, padding, buttons, coins - rather than a font-size written
   onto six components. 14px against the 12px a window in the world wears. */
.shell__section {
  --win-size: 14px;
  width: 100%;
  height: 100%;
  overflow: hidden;                  /* the window itself never scrolls... */
}

/* THE READING COLUMN. A section is as wide as the screen; what is IN it is
   not. The body keeps the parchment edge to edge and lays ONE centred grid
   track on it, --section-col wide or the screen's own width if that is
   narrower, with a gutter either side that grows with the viewport - so a
   shelf of six rows sits in the middle of the page instead of hugging its left
   edge at whatever size it was drawn for a floating box. */
.shell__section > .win__body {
  --section-col: 46em;
  display: grid;
  grid-template-columns: min(var(--section-col), 100%);
  justify-content: center;
  align-content: start;
  gap: .7em;
  padding: 1.6em clamp(1.2em, 4vw, 4em) 1em;
  overflow: auto;                    /* the body is what scrolls */
  min-height: 0;
}
.shell__section--account > .win__body { --section-col: 28em; }
.shell__section--market > .win__body { --section-col: 60em; }
.shell__section > .win__foot { padding: 0 clamp(1.2em, 4vw, 4em) 1.4em; }

/* Everything in a section body flows and WRAPS. A grid track is as wide as its
   widest child unless it is told otherwise, which is how a long tab strip used
   to push the whole window sideways and cut the last sentence in half. */
.shell__section > .win__body > * { min-width: 0; max-width: 100%; }
/* Market paints into an inner div they can replace wholesale; it is
   the column, so it stacks the same way the body would have. */
.shell__section > .win__body > [data-body] { display: grid; align-content: start; gap: .7em; min-width: 0; }
.shell__section .tabs { flex-wrap: wrap; max-width: 100%; height: auto; }
.shell__section .note-line { white-space: normal; }

/* ----------------------------------------------------------- narrow */

@media (max-width: 52em) {
  .shell__card { width: 9.5em; }
  .shell__card .doll-box { --doll-w: 6.5em; }
  /* The shelf goes back to a window's size here: on a phone the account name,
     four sections, a purse and a way out already have to wrap onto two rows,
     and 14px would make it three. */
  .shell__band { --win-size: 12px; padding: .45em .8em; }
  .shell__band .tabs { flex-wrap: wrap; height: auto; max-width: 100%; }
  .shell__who-name { font-size: 1.25em; }
}

/* ------------------------------------------------------ home: the world */

/* The strip straight under the top bar, up only when something is wrong: a
   newer build is live, or the device has no room for the world. */
.shell__world {
  margin: .6em .8em 0;
  flex-wrap: nowrap;
  gap: .9em;
}
.shell__world[hidden] { display: none; }
.shell__world .band__label { white-space: nowrap; }
.shell__world .band__mid { flex: 1 1 auto; margin: 0; min-width: 0; }
.shell__world .band__action { flex: none; }

/* ---------------------------------------------------- the corner spinner */

/* The download, in the bottom-left corner of the sign-in box and the home
   screen, from the moment the game page opens until the pack is down and verified:
   a turning ring, the percentage beside it, and on hover what is happening
   in words. Over the shell, under the curtain (200). */
.shell__fetch {
  position: fixed;
  left: 1em;
  bottom: 1em;
  z-index: 40;
  display: flex;
  align-items: center;
  gap: .5em;
  padding: .35em .6em .35em .4em;
  border-radius: 999px;
  background: var(--rim);
  box-shadow: 0 0 0 1px var(--rim-in), var(--win-shadow);
  font: var(--face-weight) var(--win-size)/1 var(--face-ui);
  color: var(--ink);
  cursor: var(--cur-arrow, default);
}
.shell__fetch[hidden] { display: none; }
.shell__fetch-ring {
  width: 1.2em;
  height: 1.2em;
  border-radius: 50%;
  border: .2em solid rgba(var(--tan-rgb), .3);
  border-top-color: var(--tan-rim);
  animation: shell-fetch-spin .9s linear infinite;
}
@keyframes shell-fetch-spin { to { transform: rotate(360deg); } }
.shell__fetch-pct { font-variant-numeric: tabular-nums; }
.shell__fetch-pct:empty { display: none; }
.shell__fetch-tip:empty { display: none; }
.shell__fetch-tip {
  position: absolute;
  left: 0;
  bottom: calc(100% + .5em);
  padding: .45em .7em;
  border-radius: 6px;
  background: var(--rim);
  box-shadow: 0 0 0 1px var(--rim-in), var(--win-shadow);
  white-space: nowrap;
  color: var(--ink-mute);
  opacity: 0;
  pointer-events: none;
  transition: opacity .15s;
}
.shell__fetch:hover .shell__fetch-tip { opacity: 1; }
