/* ==========================================================================
   Guild Website — site stylesheet

   Values settled in the Phase 0 style prototype (deleted in 4B; it's in the
   git history) and recorded in docs/aesthetic-philosophy.md. Dark theme only.
   Every color is a token on :root, so a light mode stays possible without
   rewriting anything.

   Class colors are NOT here: they live in the classes table (color_hex) and
   reach the page through /game-colors.css, which PHP generates as one
   .class-color-{slug} rule per class. Always show the class name with them.
   ========================================================================== */


/* --------------------------------------------------------------------------
   Fonts (self-hosted, openly licensed under the SIL Open Font License)
   -------------------------------------------------------------------------- */

@font-face {
  font-family: "Cormorant Garamond";
  src: url("../fonts/cormorant-garamond-600.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Source Sans 3";
  src: url("../fonts/source-sans-3-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Source Sans 3";
  src: url("../fonts/source-sans-3-700.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}


/* --------------------------------------------------------------------------
   Tokens
   -------------------------------------------------------------------------- */

:root {
  /* Iron: surfaces get lighter as they rise, instead of using shadows */
  --bg:          #141312;  /* page */
  --surface:     #1E1C1B;  /* cards, panels */
  --raised:      #282524;  /* menus, dialogs */
  --border:      #3A3634;

  /* Text */
  --text:        #EDE8E1;
  --text-muted:  #A9A29A;

  /* Identity red: deep for fills, brightened for text, links, thin lines */
  --red-fill:    #8E1B1B;
  --red-text:    #EB6163;

  /* Status: always paired with an icon and words, never color alone */
  --danger:      #FF6A3D;
  --success:     #6FBF73;
  --warning:     #E9B949;

  /* Officer notes (7D.2): pale steel, so an officer note never reads as a
     member's own words; always with its note icon, on the Accounts pages only */
  --officer:     #B4C3D6;

  /* Heatmap: jade, from few free to many free. Free half hours on the
     availability grid use the brightest, so members and the heatmap agree. */
  --heat-low:    #12302A;
  --heat-high:   #4ACFA0;

  /* Type */
  --font-head:   "Cormorant Garamond", Georgia, "Times New Roman", serif;
  --font-body:   "Source Sans 3", system-ui, -apple-system, "Segoe UI", sans-serif;

  /* Texture: faint worn metal, on the header and bands only (never behind data) */
  --texture: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9 0.04' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  --texture-strength: 0.35;

  /* Shape and spacing */
  --radius:      6px;
  --gutter:      16px;
  --tap:         44px;
  /* One half hour in the availability grid and the heatmap. Sized for a mouse
     on a monitor, and taller on a phone, where a fingertip covers more than a
     pointer does. */
  --cell-height: 24px;

  color-scheme: dark;
}

@media (max-width: 559px) {
  :root { --cell-height: 34px; }
}


/* --------------------------------------------------------------------------
   Base
   -------------------------------------------------------------------------- */

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

html { -webkit-text-size-adjust: 100%; }

/* A column, so the footer sits at the bottom of short pages */
body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 400 1rem/1.55 var(--font-body);
}
body > main { flex: 1 0 auto; width: 100%; }

h1, h2, h3 {
  font-family: var(--font-head);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: .01em;
  margin: 0 0 .5em;
}
h1 { font-size: 2.25rem; }
h2 { font-size: 1.75rem; }
h3 { font-size: 1.3rem; }

p { margin: 0 0 1em; }

a { color: var(--red-text); text-underline-offset: 3px; }

:focus-visible { outline: 2px solid var(--red-text); outline-offset: 2px; }

img, svg { max-width: 100%; }

.num   { font-variant-numeric: tabular-nums; }
.muted { color: var(--text-muted); }
.small { font-size: .875rem; }

.icon {
  width: 1.25em;
  height: 1.25em;
  flex: none;
  vertical-align: -.25em;
}

/* Holds the <symbol> icons the page uses; never displayed itself */
.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition: none !important;
    animation: none !important;
  }
}


/* --------------------------------------------------------------------------
   Layout
   -------------------------------------------------------------------------- */

.wrap {
  max-width: 1100px;
  margin: 0 auto;
  padding: 0 var(--gutter);
}

.panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px;
}
.panel.raised { background: var(--raised); }

.grid { display: grid; gap: 16px; }
@media (min-width: 760px) {
  .grid-2 { grid-template-columns: 1fr 1fr; }
  .grid-3 { grid-template-columns: repeat(3, 1fr); }
}

/* Wide tables scroll inside their box, never the whole page */
.scroll-x { overflow-x: auto; -webkit-overflow-scrolling: touch; }

.page { padding-top: 32px; padding-bottom: 48px; }
.narrow { max-width: 560px; margin-left: auto; margin-right: auto; }
/* Under a page's tabs, a narrow panel lines up with them instead of centering */
.narrow.narrow-left { margin-left: 0; }
.narrow > :last-child, .hero-frame > :last-child { margin-bottom: 0; }

/* Framed introduction inside a band: the guild on the public page, the greeting at home */
.hero-frame {
  max-width: 620px;
  margin: 0 auto;
  padding: 28px 20px;
  text-align: center;
  background: color-mix(in srgb, var(--bg), transparent 30%);
  border: 1px solid var(--border);
  outline: 1px solid color-mix(in srgb, var(--red-text), transparent 70%);
  outline-offset: -7px;
}


/* --------------------------------------------------------------------------
   Decoration: texture and dividers (frame only, never behind data)
   -------------------------------------------------------------------------- */

.textured { position: relative; isolation: isolate; }
.textured::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: var(--texture);
  opacity: var(--texture-strength);
  mix-blend-mode: overlay;
  pointer-events: none;
}

.divider {
  display: flex;
  align-items: center;
  gap: 12px;
  color: var(--red-text);
  margin: 32px 0 20px;
}
.divider::before,
.divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--border);
}
.divider svg { width: 56px; height: 16px; }


/* --------------------------------------------------------------------------
   Site header and navigation
   -------------------------------------------------------------------------- */

.site-header {
  position: relative;
  /* Above the page, so the phone menu's panel isn't painted over by the band
     or a panel below it (the texture's isolation keeps the panel's own
     z-index inside this header). */
  z-index: 10;
  background: var(--red-fill);
  color: var(--text);
  border-bottom: 1px solid #000;
}
.site-header .wrap {
  display: flex;
  align-items: center;
  gap: 16px;
  min-height: 60px;
}
.site-name {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-right: auto;
  font-family: var(--font-head);
  font-weight: 600;
  font-size: 1.35rem;
  line-height: 1.2;
  color: var(--text);
  text-decoration: none;
}
.site-emblem { flex: none; width: 36px; height: 36px; }
@media (max-width: 479px) {
  .site-name { gap: 8px; font-size: 1.2rem; }
  .site-emblem { width: 30px; height: 30px; }
}

.nav { display: flex; gap: 4px; margin: 0; padding: 0; list-style: none; }
.nav a {
  display: block;
  padding: 10px 12px;
  color: var(--text);
  text-decoration: none;
  border-radius: var(--radius);
}
.nav a:hover { background: rgba(0, 0, 0, .2); }
.nav a[aria-current] {
  background: rgba(0, 0, 0, .35);
  box-shadow: inset 0 -2px 0 var(--text);
}
.nav-desktop { flex: 1; }  /* fills the space, so links sit beside the guild name */

.header-user { color: var(--text); font-weight: 700; }
.header-form { margin: 0; }

/* Secondary button sitting on the red header */
.btn-on-red { border-color: color-mix(in srgb, var(--text), transparent 55%); }
.btn-on-red:hover { background: rgba(0, 0, 0, .25); }

/* Phone menu: a <details> element, so it opens without JavaScript.
   Wide screens show .nav-desktop and the user name and Log out instead. */
.nav-mobile summary { list-style: none; cursor: pointer; }
.nav-mobile summary::-webkit-details-marker { display: none; }
.nav-panel {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 5;
  display: grid;
  gap: 8px;
  padding: 12px var(--gutter) 16px;
  background: var(--raised);
  border-bottom: 1px solid var(--border);
}
.nav-panel .nav { flex-direction: column; }
.nav-panel .nav a[aria-current] { background: var(--surface); box-shadow: inset 3px 0 0 var(--red-text); }
.nav-panel .header-user { padding: 0 12px; color: var(--text-muted); font-weight: 400; }

/* The full header needs about 1000px for an admin (six links, a long guild
   name, the emblem), plus room for the Discord name, so narrower windows get
   the Menu button instead. A long Discord name is cut short (the whole name
   shows on hover), so it never pushes into the links. */
.site-header .wrap > .header-user { max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nav-desktop .nav a { white-space: nowrap; }
@media (max-width: 1079px) {
  .nav-desktop,
  .site-header .wrap > .header-user,
  .site-header .wrap > .header-form { display: none; }
}
@media (min-width: 1080px) {
  .nav-mobile { display: none; }
}

.site-footer {
  padding: 14px 0 18px;
  font-size: .875rem;
  text-align: center;
  color: var(--text-muted);
  border-top: 1px solid var(--border);
}
.site-footer p { margin: 0; }


/* --------------------------------------------------------------------------
   Buttons
   -------------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: var(--tap);
  padding: 10px 18px;
  font: 700 1rem/1 var(--font-body);
  border: 1px solid transparent;
  border-radius: var(--radius);
  cursor: pointer;
  text-decoration: none;
}
.btn-primary {
  background: var(--red-fill);
  color: var(--text);
  border-color: color-mix(in srgb, var(--red-fill), white 15%);
}
.btn-primary:hover { background: color-mix(in srgb, var(--red-fill), white 8%); }

.btn-secondary {
  background: transparent;
  color: var(--text);
  border-color: var(--border);
}
.btn-secondary:hover { background: var(--raised); }

/* Destructive: pair with a warning icon, explicit wording, and a confirm step */
.btn-danger {
  background: transparent;
  color: var(--danger);
  border-color: var(--danger);
}
.btn-danger:hover { background: color-mix(in srgb, var(--danger), transparent 88%); }
/* Destructive but quiet: red words with no box, for a Cancel that sits apart from the other tools (5J) */
.btn-quiet-danger { background: transparent; color: var(--danger); border-color: transparent; }
.btn-quiet-danger:hover { background: color-mix(in srgb, var(--danger), transparent 88%); }

.btn-row { display: flex; flex-wrap: wrap; gap: 12px; }
.btn-row form { margin: 0; }

.btn-small { min-height: 32px; padding: 5px 12px; font-size: .9375rem; }

/* A button that looks like a link, for small actions in lists and sentences */
.btn-link {
  padding: 0;
  font: inherit;
  color: var(--red-text);
  text-decoration: underline;
  text-underline-offset: 3px;
  background: none;
  border: 0;
  cursor: pointer;
}


/* --------------------------------------------------------------------------
   Forms
   -------------------------------------------------------------------------- */

.field { display: grid; gap: 6px; margin-bottom: 16px; }
.field > label,
.legend { font-weight: 700; }
.hint { font-size: .875rem; color: var(--text-muted); }

input[type=text],
input[type=password],
input[type=search],
input[type=url],
input[type=date],
select,
textarea {
  width: 100%;
  min-height: var(--tap);
  padding: 8px 12px;
  font: inherit;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
input:hover, select:hover, textarea:hover { border-color: var(--text-muted); }

.field.has-error input,
.field.has-error select,
.field.has-error textarea { border-color: var(--danger); }
.error-text {
  display: flex;
  gap: 6px;
  align-items: center;
  font-size: .9375rem;
  color: var(--danger);
}

fieldset { border: 0; padding: 0; margin: 0 0 16px; }

/* Large tap-target choices (roles and similar) */
.choice-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-top: 6px; }
.choice { position: relative; }
.choice input { position: absolute; inset: 0; margin: 0; opacity: 0; cursor: pointer; }
.choice span {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  min-height: 64px;
  padding: 10px 6px;
  font-size: .9375rem;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.choice input:checked + span {
  background: var(--raised);
  border-color: var(--red-text);
  box-shadow: inset 0 0 0 1px var(--red-text);
}
.choice input:checked + span::after { content: "Selected"; font-size: .75rem; color: var(--red-text); }
.choice input:focus-visible + span { outline: 2px solid var(--red-text); outline-offset: 2px; }

.check { display: flex; gap: 10px; align-items: center; min-height: var(--tap); }
.check-row { display: flex; flex-wrap: wrap; gap: 0 24px; }
.check input { width: 22px; height: 22px; accent-color: var(--red-fill); }


/* --------------------------------------------------------------------------
   Alerts
   -------------------------------------------------------------------------- */

.alert {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  margin-bottom: 12px;
  padding: 12px 14px;
  background: var(--surface);
  border: 1px solid;
  border-left-width: 4px;
  border-radius: var(--radius);
}
.alert .icon { margin-top: 2px; }
.alert strong { display: block; }
.alert-success { border-color: var(--success); }
.alert-success .icon { color: var(--success); }
.alert-warning { border-color: var(--warning); }
.alert-warning .icon { color: var(--warning); }
.alert-danger { border-color: var(--danger); }
.alert-danger .icon { color: var(--danger); }


/* --------------------------------------------------------------------------
   Tables (roster, logs, admin lists)
   -------------------------------------------------------------------------- */

table { width: 100%; border-collapse: collapse; }
th, td {
  padding: 8px 10px;
  text-align: left;
  vertical-align: middle;
  border-bottom: 1px solid var(--border);
}
th {
  font-size: .8125rem;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--text-muted);
}
table.compact td, table.compact th { padding: 6px 10px; }

.class-name { font-weight: 700; }
.role { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.tag {
  padding: 1px 7px;
  font-size: .75rem;
  color: var(--text-muted);
  white-space: nowrap;
  border: 1px solid var(--border);
  border-radius: 999px;
}
.pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 12px;
  font-size: .9375rem;
  border: 1px solid var(--border);
  border-radius: 999px;
}


/* --------------------------------------------------------------------------
   Guild heatmap (the home page and the Guild heatmap tab): a table like the
   availability grid, one button per half hour showing how many are usually
   free, with the best evenings or who is free beside it. Brighter jade means
   more people, and every cell shows its count, so meaning never rests on
   color alone.
   -------------------------------------------------------------------------- */

.heatmap { display: grid; gap: 20px 28px; align-items: start; }
@media (min-width: 960px) {
  /* Stretch, so a chosen half hour's list can fill the heatmap's own height (see .heat-slot) */
  .heatmap { grid-template-columns: max-content minmax(0, 1fr); align-items: stretch; }
}

.heat-heading { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 16px; margin-bottom: 12px; }
.heat-heading h2 { margin: 0; font-size: 1.5rem; }
.heat-zone { margin: 0; color: var(--text-muted); }
.heat-more { margin-left: auto; }
.heat-note { margin: -4px 0 12px; color: var(--text-muted); }
/* The level choice (5A): the line saying what's applied, the home page's small
   menu in the heading row, and a level after each name in the list. */
.heat-level-line { color: var(--text); }
.heat-home-level { margin: 0; cursor: default; }
.heat-home-level select { min-height: 32px; padding-top: 3px; padding-bottom: 3px; font-size: .9375rem; max-width: 230px; }
.home-heatmap.is-collapsed .heat-home-level { display: none; }
.heat-person-level { flex: none; min-width: 22px; font-weight: 700; text-align: right; color: var(--text-muted); cursor: default; }
.heat-person-level.is-unknown { font-weight: 400; }

/* Menus above the heatmap, with no visible labels (like the roster's). Seven
   don't fit one row at 1100px without cutting their words short (5A), so
   there are two: what to highlight (week, group size, session, raids), then
   who counts (role, rank, and level, which is wider for a character's name). */
.heat-filters { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; margin-bottom: 16px; padding: 10px; }
@media (min-width: 760px) {
  .heat-filters { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .heat-filter-level { grid-column: span 2; }
}
.heat-filters select.is-set { border-color: var(--red-text); }

.heat-grid { width: auto; table-layout: fixed; border-collapse: separate; border-spacing: 3px 2px; }
.heat-grid th,
.heat-grid td { padding: 0; border: 0; }
/* Day names stay in view while a tall heatmap scrolls. The side shadows fill
   the gaps between them, so nothing scrolling underneath shows through. */
.heat-grid thead > tr > * {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--surface);
  box-shadow: -3px 0 0 var(--surface), 3px 0 0 var(--surface);
}
.heat-grid .heat-corner { width: 64px; }
.heat-grid thead th {
  width: 58px;
  padding: 4px 0 6px;
  font-size: 1rem;
  letter-spacing: 0;
  text-transform: none;
  text-align: center;
  color: var(--text);
}
.heat-grid thead th.is-past { color: var(--text-muted); }
.heat-grid thead th.is-today { box-shadow: inset 0 -3px 0 var(--red-text), -3px 0 0 var(--surface), 3px 0 0 var(--surface); }
.heat-date { font-weight: 400; color: var(--text-muted); }
.heat-grid tbody th {
  padding-right: 8px;
  font-size: .875rem;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  text-align: right;
  white-space: nowrap;
  color: var(--text-muted);
}
/* A little space above each hour, and a dashed line at midnight */
.heat-grid tr.is-hour > * { padding-top: 3px; }
.heat-grid tr.is-midnight > * { padding-top: 5px; border-top: 1px dashed var(--text-muted); }

/* A half hour. Nobody free: dark and empty. */
.heat-cell {
  position: relative;
  display: grid;
  place-items: center;
  width: 100%;
  height: var(--cell-height);
  padding: 0;
  font: 700 .875rem/1 var(--font-body);
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
  background: var(--bg);
  border: 0;
  border-radius: 3px;
  cursor: pointer;
  /* A finger scrolls the page over the heatmap as it does everywhere else;
     this only tells the browser not to wait for a second tap that would zoom. */
  touch-action: manipulation;
}
/* Short of a group, two dim steps: a faint tint with a quiet count, then,
   once no more than a quarter short ("nearly a group", 3 of 5), a clearer
   jade with a brighter count. */
.heat-cell.is-few { font-weight: 400; color: var(--text-muted); background: color-mix(in srgb, var(--heat-low) 40%, var(--bg)); }
.heat-cell.is-near { font-weight: 400; color: var(--text); background: color-mix(in srgb, var(--heat-high) 10%, var(--heat-low)); }
/* A whole group or more: ten steps of full jade, from exactly a group up to
   the busiest half hour shown. Steps 1-3 carry light numbers and 4-10 dark
   ones, and the jump between them skips the middle shades, where neither
   would reach 4.5:1. */
.heat-1  { color: var(--text); background: color-mix(in srgb, var(--heat-high) 32%, var(--heat-low)); }
.heat-2  { color: var(--text); background: color-mix(in srgb, var(--heat-high) 37%, var(--heat-low)); }
.heat-3  { color: var(--text); background: color-mix(in srgb, var(--heat-high) 42%, var(--heat-low)); }
.heat-4  { color: var(--bg); background: color-mix(in srgb, var(--heat-high) 59%, var(--heat-low)); }
.heat-5  { color: var(--bg); background: color-mix(in srgb, var(--heat-high) 66%, var(--heat-low)); }
.heat-6  { color: var(--bg); background: color-mix(in srgb, var(--heat-high) 73%, var(--heat-low)); }
.heat-7  { color: var(--bg); background: color-mix(in srgb, var(--heat-high) 80%, var(--heat-low)); }
.heat-8  { color: var(--bg); background: color-mix(in srgb, var(--heat-high) 87%, var(--heat-low)); }
.heat-9  { color: var(--bg); background: color-mix(in srgb, var(--heat-high) 93%, var(--heat-low)); }
.heat-10 { color: var(--bg); background: var(--heat-high); }
/* Raids, when a raid size is highlighted: a ring just inside the cell, in the
   count's own color, dashed for nearly a raid (7-9 of 10) and solid for a
   whole raid. The sliver of jade outside the ring keeps it from blending
   into the dark around the cell, on dim and bright jade alike. */
.heat-cell.is-near-raid { outline: 2px dashed currentColor; outline-offset: -4px; }
.heat-cell.is-raid { outline: 2px solid currentColor; outline-offset: -4px; }
/* A group free for the whole session from here: a corner notch in the count's color */
.heat-cell.is-start::after {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  border-style: solid;
  border-width: 0 10px 10px 0;
  border-color: transparent currentColor transparent transparent;
}
/* Your own times: a bar down the left edge, so your evenings read as a line */
.heat-cell.is-yours::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 4px;
  background: currentColor;
  border-radius: 3px 0 0 3px;
}
.heat-cell.is-skipped { font-weight: 400; background: transparent; border: 1px dashed var(--border); cursor: default; }
/* Hover and the chosen half hour draw outside the cell, so a raid ring stays */
.heat-cell:hover { box-shadow: 0 0 0 1px var(--text-muted); }
.heat-cell.is-chosen { box-shadow: 0 0 0 2px var(--text); }
.heat-cell:focus-visible { outline: 2px solid var(--red-text); outline-offset: 1px; }

/* A planned event: a thin red frame around its half hours, drawn on the table
   cells in the gaps between the buttons, so every count, ring, notch, and bar
   stays as it is. Each cell draws the frame's sides, running into the gaps
   above and below; the first and last close it. Hour rows have 3px of space
   above, and the midnight row 5px under its dashed line, so the frame's top
   edge moves down to sit just above the button. The chosen half hour's
   outline is drawn later, over the frame. */
.heat-grid tbody td { position: relative; }
.heat-grid td.is-planned::before {
  content: "";
  position: absolute;
  top: -1px;
  bottom: -1px;
  left: -2px;
  right: -2px;
  border: 0 solid var(--red-text);
  border-width: 0 2px;
  pointer-events: none;
}
.heat-grid tr.is-midnight > td.is-planned::before { top: -2px; }
.heat-grid td.is-planned-first::before { top: -2px; border-top-width: 2px; border-top-left-radius: 6px; border-top-right-radius: 6px; }
.heat-grid tr.is-hour > td.is-planned-first::before { top: 1px; }
.heat-grid tr.is-midnight > td.is-planned-first::before { top: 3px; }
.heat-grid td.is-planned-last::before { bottom: -2px; border-bottom-width: 2px; border-bottom-left-radius: 6px; border-bottom-right-radius: 6px; }
/* Keyboard focus is red too, so inside a frame it moves just inside the button */
.heat-grid td.is-planned > .heat-cell:focus-visible { outline-offset: -3px; }
/* The calendar mark over a day with a planned event, opening its first event
   (an empty one keeps the day names level) */
.heat-day-mark { display: grid; place-items: center; width: 30px; height: 20px; margin: -2px auto 0; color: var(--red-text); border-radius: 4px; }
a.heat-day-mark:hover { color: var(--text); background: var(--raised); }
/* A day with an event you've signed up for: a check in the calendar, on red */
a.heat-day-mark.is-yours { color: var(--text); background: var(--red-fill); }
a.heat-day-mark.is-yours:hover { background: var(--red-fill); box-shadow: 0 0 0 1px var(--text); }
.heat-day-mark .icon { width: 16px; height: 16px; }

.heat-legend { display: flex; flex-wrap: wrap; gap: 6px 18px; max-width: 480px; margin: 12px 0 0; padding: 0; font-size: .875rem; color: var(--text-muted); list-style: none; }
.heat-legend li { display: inline-flex; align-items: center; gap: 8px; }
.heat-key { width: 30px; height: 20px; cursor: default; }
.heat-key:hover { box-shadow: none; }
.heat-key-frame { display: inline-block; width: 30px; height: 20px; border: 2px solid var(--red-text); border-radius: 6px; }
.heat-basis { margin: 8px 0 0; font-size: .875rem; color: var(--text-muted); }

/* Beside the heatmap: the best evenings, or who is free in the chosen half hour */
.heat-details { min-width: 0; }
/* A chosen half hour's list is as tall as the heatmap and scrolls inside it,
   so a busy evening's forty names don't push the page down and the grid stays
   in view while you compare half hours (4B). */
@media (min-width: 960px) {
  .heat-details { position: relative; }
  .heat-slot { position: absolute; inset: 0; padding-right: 10px; overflow-y: auto; overscroll-behavior: contain; }
}
.heat-details-title { margin-bottom: 8px; font-size: 1.3rem; }
.heat-zone-hint { margin-top: -8px; font-style: italic; }
.heat-best { display: grid; gap: 8px; margin: 0 0 12px; padding: 0; list-style: none; }
.heat-best-button {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 2px 16px;
  width: 100%;
  padding: 10px 14px;
  font: inherit;
  text-align: left;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  cursor: pointer;
}
.heat-best-button:hover { border-color: var(--text-muted); }
.heat-best-count { color: var(--text-muted); }
/* Under best evenings that all fall short of a group (the review's session 3) */
.heat-best-short { margin: 0 0 12px; font-size: .875rem; }
.heat-summary .heat-best-short { margin: 0; }

.heat-back { margin-bottom: 10px; }
.heat-slot-day { margin: 0; font-size: .875rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--text-muted); }
.heat-slot-time { margin: 0; font-size: 1.75rem; }
.heat-slot-count { margin: 2px 0 12px; color: var(--text-muted); }

/* Role boxes, like the mains summary: icon, count, and "+N" who can switch */
.heat-roles { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 4px; padding: 0; list-style: none; }
.heat-roles li {
  display: grid;
  grid-template-columns: auto auto;
  align-items: center;
  gap: 1px 8px;
  padding: 5px 14px 3px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.heat-role-icon { width: 30px; height: 30px; border-radius: 3px; }
.heat-roles-count { font-size: 1.375rem; line-height: 1; }
.heat-roles-flex { grid-column: 1 / -1; justify-self: center; font-size: .8125rem; line-height: 1.2; color: var(--text-muted); }

.heat-group { margin-top: 12px; }
.heat-group-title { display: flex; align-items: center; gap: 8px; margin: 0 0 4px; font: 700 .9375rem/1.3 var(--font-body); color: var(--text-muted); }
.heat-group-title .game-icon { width: 20px; height: 20px; border-radius: 3px; }
.heat-people { margin: 0; padding: 0; list-style: none; }
.heat-person { display: flex; align-items: center; gap: 8px; min-height: 36px; padding: 3px 8px; border-top: 1px solid var(--border); }
.heat-person:last-child { border-bottom: 1px solid var(--border); }
/* Your own line: the red edge, as on the roster */
.heat-person.is-you { box-shadow: inset 3px 0 0 var(--red-text); }
.heat-person-kind { display: inline-flex; flex: none; gap: 3px; }
.heat-icon { width: 26px; height: 26px; border-radius: 3px; }
/* A name short of room wraps between its two parts rather than being cut short (5I) */
.heat-person-name { min-width: 0; font-size: 1.0625rem; line-height: 1.2; overflow-wrap: break-word; }
.heat-mark { display: inline-flex; flex: none; color: var(--text-muted); }
.heat-mark .icon { width: 18px; height: 18px; }
.heat-hours { flex: none; margin-left: auto; padding-left: 8px; font-size: .9375rem; color: var(--text-muted); white-space: nowrap; }
.heat-person-more { color: var(--text-muted); }

/* In a chosen half hour: the events planned then, and for officers, planning one */
.heat-planned {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: 0 10px;
  margin: 0 0 10px;
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-left: 3px solid var(--red-text);
  border-radius: var(--radius);
}
.heat-planned .icon { grid-row: span 2; color: var(--red-text); }
.heat-planned > span { overflow-wrap: anywhere; }
.heat-planned-when { color: var(--text-muted); }
.heat-plan { margin: 0 0 12px; }

/* Under the best evenings: the events coming up, or planned that week */
.heat-events { margin-top: 22px; }
.heat-event-list { display: grid; gap: 8px; margin: 0; padding: 0; list-style: none; }
.heat-event {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: "when status" "title status" "detail status";
  align-items: center;
  gap: 0 12px;
  padding: 8px 12px;
  color: var(--text);
  text-decoration: none;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.heat-event:hover { border-color: var(--text-muted); }
.heat-event.is-you { box-shadow: inset 4px 0 0 var(--red-text); }
.heat-event-when { grid-area: when; font-size: .75rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--text-muted); }
.heat-event-title { grid-area: title; min-width: 0; font-size: 1.0625rem; overflow-wrap: anywhere; }
.heat-event.is-cancelled .heat-event-title { color: var(--text-muted); text-decoration: line-through; }
.heat-event-detail { grid-area: detail; font-size: .875rem; color: var(--text-muted); }
.heat-event-status { grid-area: status; }
.heat-events-all { margin: 8px 0 0; }

/* The home page: This week and the heatmap panel under the greeting. The
   heatmap starts collapsed to one line of best evenings (5D.2); Show opens it. */
.home-panels { display: grid; gap: 24px; padding-top: 24px; }
.heat-timezone { max-width: 420px; }
.home-week .event-lines { margin-top: 4px; }
.home-week-empty { margin: 0; }
.home-week-more { margin: 8px 0 0 14px; }
/* Collapsed (7Q): the first event's line and "and N more", which opens it again */
.home-week.is-collapsed .event-lines > li:nth-child(n+2),
.home-week.is-collapsed .home-week-more-open,
.home-week:not(.is-collapsed) .home-week-more-closed { display: none; }
.home-week .heat-heading { align-items: center; }
/* The whole heading row opens and closes it; hovering it lights up Hide/Show */
.heat-heading.is-toggle-area { cursor: pointer; }
.heat-heading.is-toggle-area:hover .heat-toggle { background: var(--raised); border-color: var(--text-muted); }
.heat-toggle { gap: 6px; }
.heat-toggle .icon { width: 18px; height: 18px; transition: transform .15s ease; }
.heat-toggle[aria-expanded="true"] .icon { transform: rotate(180deg); }
/* Guild News opens a few lines at a time: its chevron turns over only once the next press closes it (7Q) */
.home-news .heat-toggle[aria-expanded="true"]:not(.is-hide) .icon { transform: none; }
.home-heatmap.is-collapsed .heat-heading { margin-bottom: 10px; }
.heat-summaries { display: grid; gap: 10px; }
.heat-summary { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; }
.heat-summary-label { margin-right: 4px; font-weight: 700; color: var(--text-muted); }
.heat-summary-evening {
  padding: 6px 14px;
  font: inherit;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 999px;
  cursor: pointer;
}
.heat-summary-evening:hover { border-color: var(--text-muted); }
/* The events coming up, on the collapsed line: always one line, so long
   titles are cut short (whole on hover) */


/* --------------------------------------------------------------------------
   Availability: your typical week as a table, days across (Monday first) and
   the guild's evening hours down the side, one button per half hour. Free
   half hours are filled jade; empty ones are dark and outlined, so the fill,
   not the hue, carries the meaning. Away dates sit in a panel beside it.
   -------------------------------------------------------------------------- */

.avail-intro { color: var(--text-muted); }
.avail-stale p { margin: 2px 0 10px; }
.avail-stale form { margin: 0; }

.avail-layout { display: grid; gap: 16px; align-items: start; }
@media (min-width: 960px) {
  .avail-layout { grid-template-columns: minmax(0, 1fr) 310px; }
}

.avail-week-heading { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 4px 16px; margin-bottom: 8px; }
.avail-week-heading h2,
.avail-away h2 { margin-bottom: 0; font-size: 1.5rem; }
.avail-zone { margin: 0; color: var(--text-muted); }

/* Painting drags across the cells, so nothing in the grid selects as text, and
   a long press doesn't raise a phone's own copy and share menu over it */
.avail-grid {
  table-layout: fixed;
  border-collapse: separate;
  border-spacing: 3px 2px;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}
.avail-grid th,
.avail-grid td { padding: 0; border: 0; }
.avail-grid .avail-corner { width: 64px; }
/* Day names stay in view while a tall grid scrolls */
.avail-grid thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: 6px 0;
  font-size: 1rem;
  letter-spacing: 0;
  text-transform: none;
  text-align: center;
  color: var(--text);
  background: var(--surface);
}
.avail-grid tbody th {
  padding-right: 8px;
  font-size: .875rem;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  text-align: right;
  white-space: nowrap;
  color: var(--text-muted);
}
/* A little space above each hour, and a dashed line at midnight */
.avail-grid tr.is-hour > * { padding-top: 4px; }
.avail-grid tr.is-midnight > * { padding-top: 6px; border-top: 1px dashed var(--text-muted); }

/* "+ 3–6 pm" above the grid and "+ 1–4 am" below: up to three more hours on
   either side, for members playing across time zones. A quiet dashed bar,
   gone once the hours show. The heatmap uses the same bars for the quieter
   hours outside its evening, where fewer than a group are free (4B). */
.avail-grid .avail-more td,
.heat-grid .heat-more td { padding: 4px 0; }
.avail-more-button,
.heat-more-button {
  display: block;
  width: 100%;
  padding: 2px 0;
  font: inherit;
  font-size: .875rem;
  color: var(--text-muted);
  background: transparent;
  border: 1px dashed var(--border);
  border-radius: 3px;
  cursor: pointer;
}
.avail-more-button:hover,
.heat-more-button:hover { color: var(--text); border-color: var(--text-muted); }

.avail-cell {
  display: block;
  width: 100%;
  height: var(--cell-height);
  padding: 0;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 3px;
  cursor: pointer;
  /* A finger drag over the cells paints instead of scrolling the page: the
     gesture belongs to the grid, as it does with a mouse. Scrolling is still
     there on the times down the side, the "+" bars, and everywhere off the
     grid. The second line keeps two-finger zooming where browsers know it. */
  touch-action: none;
  touch-action: pinch-zoom;
}
.avail-cell:hover { border-color: var(--text-muted); }
.avail-cell[aria-checked="true"] { background: var(--heat-high); border-color: var(--heat-high); }
/* While dragging: what each cell will be when the mouse button is let go */
.avail-cell.paint-on { background: var(--heat-high); border-color: var(--text); }
.avail-cell.paint-off { background: var(--bg); border: 1px dashed var(--text); }
.avail-cell:focus-visible { outline: 2px solid var(--red-text); outline-offset: 1px; }

.avail-toolbar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 16px; margin-top: 12px; }
.avail-status { display: flex; flex: 1 1 300px; flex-wrap: wrap; align-items: center; gap: 4px 14px; margin: 0; }
.avail-save.is-error { display: inline-flex; align-items: center; gap: 6px; color: var(--danger); }
.avail-empty-week { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 8px; margin: 10px 0 0; }

/* Show my name on the guild heatmap: saves as it changes, like the grid */
.avail-name { margin-top: 16px; padding-top: 8px; border-top: 1px solid var(--border); }
.avail-name-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0 16px; }
.avail-name .hint { margin: 0; }

.away-list { margin: 12px 0 0; padding: 0; list-style: none; }
.away-item { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 2px 12px; padding: 8px 0; border-top: 1px solid var(--border); }
.away-item:last-child { border-bottom: 1px solid var(--border); }
.away-dates { display: inline-flex; align-items: baseline; gap: 8px; font-weight: 700; }
.away-actions { display: flex; gap: 14px; }
.away-actions form { margin: 0; }
.away-form { margin-top: 20px; }
.away-form h3 { margin-bottom: .4em; }
.away-form .field { margin-bottom: 12px; }
.narrow .away-fields { display: grid; gap: 0 16px; }
@media (min-width: 560px) {
  .narrow .away-fields { grid-template-columns: 1fr 1fr; }
}


/* --------------------------------------------------------------------------
   Admin
   -------------------------------------------------------------------------- */

.btn:disabled { opacity: .45; cursor: not-allowed; }

textarea { min-height: 7rem; resize: vertical; line-height: 1.5; }

.admin-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 8px;
  margin: 0 0 24px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--border);
}
.admin-tabs a {
  display: inline-block;
  padding: 10px 12px;
  color: var(--text-muted);
  text-decoration: none;
  border-radius: var(--radius);
}
.admin-tabs a:hover { color: var(--text); background: var(--surface); }
.admin-tabs a[aria-current] { color: var(--text); background: var(--raised); box-shadow: inset 0 -2px 0 var(--red-text); }

.link-card { display: block; color: var(--text); text-decoration: none; }
.link-card:hover { border-color: var(--text-muted); }
.link-card h2 { color: var(--red-text); }
.link-card > :last-child { margin-bottom: 0; }

.settings-form { display: grid; gap: 16px; }
.field-pair { display: grid; gap: 0 16px; }
@media (min-width: 760px) {
  .field-pair { grid-template-columns: repeat(2, minmax(0, 240px)); }
}
.settings-form .panel > .field:last-child { margin-bottom: 0; }
/* Settings' recipe lists (the feature review's P5 and P6): not found on Wowhead, and renamed there */
.wowhead-list { margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--border); }
.wowhead-list h3 { margin: 0 0 4px; }
.wowhead-list .hint { margin: 0 0 8px; }
.wowhead-list-groups { display: grid; gap: 4px; margin: 0 0 12px; padding: 0; list-style: none; }
.wowhead-list-groups:last-child { margin-bottom: 0; }
.wowhead-list-profession { color: var(--text-muted); }
/* Events in Discord (5C) */
.discord-form .panel > p,
.discord-form .panel > .alert { margin-bottom: 16px; }
/* The events channel's id (6B): a Discord id, 17 to 20 digits, in a box that size */
input[type=text].input-id { width: 16em; font-variant-numeric: tabular-nums; }
.confirm-panel { border-color: var(--warning); }
.confirm-panel ul { margin: 0 0 12px; padding-left: 20px; }

/* Game data lists */
.game-list { margin-bottom: 16px; }
.item-list { list-style: none; margin: 0 0 16px; padding: 0; }
.item-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
  padding: 10px 0;
  border-bottom: 1px solid var(--border);
}
.item-name { display: flex; gap: 8px; flex: 1 1 260px; margin: 0; }
.item-name input { flex: 1; min-width: 0; }
.item-actions { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; }
.item-error { flex-basis: 100%; }
/* Each entry's icon, its place held when there's none, and the file it would be (the feature review's P7) */
.item-icon { display: inline-flex; flex: none; width: 26px; }
.item-icon .inline-icon { width: 26px; height: 26px; margin: 0; vertical-align: 0; }
.item-no-icon { flex-basis: 100%; font-size: .875rem; }
.class-name .inline-icon { width: 28px; height: 28px; margin-right: 10px; vertical-align: -4px; }
.item-row.is-hidden .item-name input { color: var(--text-muted); }
.item-add { display: grid; gap: 6px; }
.item-add > label { font-weight: 700; }

/* Classes */
.class-list { display: grid; gap: 16px; }
.class-item { margin: 0; }
.class-item.is-hidden { border-style: dashed; }
.class-heading { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; margin-bottom: 12px; }
.class-heading h2 { margin: 0; }
.class-heading .item-actions { margin-left: auto; }
.class-fields { display: grid; gap: 0 16px; }
@media (min-width: 760px) {
  .class-fields { grid-template-columns: 2fr 1fr 2fr; }
}
input[type=color] {
  width: 100%;
  min-height: var(--tap);
  padding: 4px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  cursor: pointer;
}
.role-checks { display: flex; flex-wrap: wrap; gap: 0 16px; }
.class-form .error-text { margin: 0 0 8px; }

/* Race and class pair grid */
.pair-grid th, .pair-grid td { text-align: center; }
.pair-grid tbody th {
  min-width: 9rem;
  text-align: left;
  text-transform: none;
  letter-spacing: 0;
  font-size: 1rem;
  color: var(--text);
}
.pair-grid thead th { text-transform: none; letter-spacing: 0; font-size: .9375rem; color: var(--text); }
.pair-grid input[type=checkbox] { width: 24px; height: 24px; accent-color: var(--red-fill); cursor: pointer; }
.pair-actions { margin-top: 16px; }


/* --------------------------------------------------------------------------
   Characters
   -------------------------------------------------------------------------- */

/* Layout rules like .field { display: grid } would otherwise beat [hidden] */
[hidden] { display: none !important; }

.page-heading { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; margin-bottom: 16px; }
.page-heading h1 { margin: 0 auto 0 0; }

/* Each card is its own height (7C.2), so opening one card's recipes doesn't stretch its neighbours */
.character-list { display: grid; align-items: start; gap: 16px; margin: 0; padding: 0; list-style: none; }
@media (min-width: 760px) {
  .character-list { grid-template-columns: repeat(2, 1fr); }
}
.character-card { display: flex; flex-direction: column; margin: 0; scroll-margin-top: 12px; }
.character-card.is-main { border-color: color-mix(in srgb, var(--red-text), transparent 50%); }
.character-heading { display: flex; align-items: center; gap: 4px 10px; margin: 0 0 12px; }
.character-kind-icons { display: inline-flex; flex: none; gap: 4px; }
.character-name { min-width: 0; margin: 0; overflow-wrap: break-word; }
.character-name .main-star { vertical-align: -2px; }
/* A main character: a small red star after the name ("Main character" on hover and for screen readers) */
.main-star { display: inline-flex; align-items: center; color: var(--red-text); }
.main-star .icon { width: 16px; height: 16px; vertical-align: 0; }
.character-heading .main-star .icon { width: 22px; height: 22px; }
.character-details {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 4px 12px;
  align-items: baseline;
  margin: 0 0 16px;
}
/* Your own level, changed in place (5A, characters/_level.php): "Level 23"
   and a small "+", in the home greeting and on each My characters card. The
   number is a button that opens a box; "Add level" is quiet until it's set. */
.level-control { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.level-number { padding: 2px 6px; border: 1px solid transparent; border-radius: 4px; background: none; color: inherit; font: inherit; font-weight: 700; cursor: pointer; }
.level-number:hover,
.level-number:focus-visible { border-color: var(--border); background: var(--raised); }
.level-control.is-empty .level-number { font-weight: 400; color: var(--text-muted); text-decoration: underline; text-underline-offset: 3px; }
.level-plus { display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px; padding: 0; border: 1px solid var(--border); border-radius: 4px; background: var(--raised); color: var(--text); font: inherit; font-size: 1.125rem; font-weight: 700; line-height: 1; cursor: pointer; }
.level-plus:hover,
.level-plus:focus-visible { border-color: var(--red-text); color: var(--red-text); }
.level-editing { display: inline-flex; align-items: center; gap: 6px; font-weight: 700; }
/* The check mark that saves the typed level: big enough for a thumb */
.level-confirm { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; padding: 0; border: 1px solid var(--red-fill); border-radius: 4px; background: var(--red-fill); color: var(--text); cursor: pointer; }
.level-confirm:hover,
.level-confirm:focus-visible { border-color: var(--red-text); }
.level-confirm .icon { width: 18px; height: 18px; }
.level-editing label { margin: 0; }
/* input[type=text] is full width; a level needs room for three digits */
input[type=text].input-level { width: 4.5em; }
.level-editing label { white-space: nowrap; }
.level-editing input[type=text].input-level { flex: none; min-height: 32px; padding: 2px 6px; text-align: center; }
.level-status { font-size: .875rem; color: var(--red-text); }
.level-status:empty { display: none; }
/* A new recipe name's lookup on Wowhead (7I.2): what it's doing and what came of it, never an error's red. */
.level-status.is-note { color: var(--text-muted); }
.level-note { display: block; margin-top: 2px; font-size: .875rem; }
[hidden].level-note, [hidden].level-plus, [hidden].level-editing, [hidden].level-number { display: none; }
.home-greeting-kind .level-control { margin-left: 8px; }

/* Your roster note in the greeting (5E.2): the words as a button, the "5d"
   mark, the ×, and the box that replaces them while editing */
.home-greeting-note { margin-top: 12px; text-align: center; line-height: 1.6; }
/* The words flow as text, so the "5d" mark and the × follow the last line */
.note-text { display: inline; max-width: 100%; padding: 2px 6px; border: 1px solid transparent; border-radius: 4px; background: none; color: inherit; font: inherit; overflow-wrap: anywhere; cursor: pointer; -webkit-box-decoration-break: clone; box-decoration-break: clone; }
.note-text:hover,
.note-text:focus-visible { border-color: var(--border); background: var(--raised); }
.note-text .icon { width: 18px; height: 18px; margin-right: 4px; vertical-align: -4px; color: var(--text-muted); }
.note-days { margin-left: 6px; }
.note-remove { margin-left: 4px; vertical-align: middle; }
.home-greeting-note.is-empty .note-text { color: var(--text-muted); }
.home-greeting-note.is-empty .note-text [data-note-text] { text-decoration: underline; text-underline-offset: 3px; }
.note-days { font-size: .875rem; font-weight: 700; color: var(--text-muted); white-space: nowrap; cursor: default; }
.note-remove { display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px; padding: 0; border: 1px solid var(--border); border-radius: 4px; background: var(--raised); color: var(--text-muted); font: inherit; font-size: 1.125rem; line-height: 1; cursor: pointer; }
.note-remove:hover,
.note-remove:focus-visible { border-color: var(--red-text); color: var(--red-text); }
.note-editing { display: flex; align-items: center; gap: 6px; }
.note-editing input[type=text].input-note { flex: 1 1 auto; min-width: 0; min-height: 32px; padding: 2px 8px; }
[hidden].note-editing, [hidden].note-remove, [hidden].note-days, [hidden].note-text { display: none; }

/* On the roster: one line under the member's name, before the characters,
   with Clear note for officers */
.roster-note { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; margin: 4px 0 2px; }
.roster-note .icon { flex: none; width: 18px; height: 18px; color: var(--red-text); }
.roster-note-text { overflow-wrap: anywhere; }
.roster-note-clear { margin: 0 0 0 auto; }

.character-details dt { color: var(--text-muted); }
.character-details dd { margin: 0; overflow-wrap: anywhere; }
.character-actions { margin-top: auto; gap: 8px; }
.character-actions form { margin: 0; }

/* My characters as one row per character on a monitor (7O, the testers'
   idea, which Alex chose over the cards): the name and level
   with the buttons at the right, then two columns, the details (roles,
   specs, riding) with attunements and reputations under them, and the
   professions two abreast. Below 960px the cards are as they were. */
@media (min-width: 960px) {
  .character-list { grid-template-columns: 1fr; }
  .character-card {
    display: grid;
    grid-template-columns: minmax(320px, 390px) minmax(0, 1fr) auto;
    grid-template-rows: auto auto 1fr;
    grid-template-areas:
      "head       head    actions"
      "details    recipes recipes"
      "milestones recipes recipes";
    align-items: start;
    gap: 4px 32px;
  }
  .character-list .character-heading { grid-area: head; }
  .character-list .character-details { grid-area: details; margin-bottom: 12px; }
  .character-list .character-recipes { grid-area: recipes; display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 12px 28px; align-items: start; }
  .character-list .character-milestones { grid-area: milestones; }
  .character-list .character-actions { grid-area: actions; align-self: center; justify-content: flex-end; flex-wrap: nowrap; margin: 0 0 12px; }
  .character-list .character-actions .btn { min-height: 34px; padding-top: 4px; padding-bottom: 4px; }
}

/* A role on the card with its spec and build note (7O, characters/_role_build.php):
   the role, the spec's menu, and a quiet "…" on one line; the note, or its box, under them */
.role-build { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; }
.role-build-line { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; }
.role-build-role,
.role-build-spec { display: inline-flex; align-items: center; white-space: nowrap; }
.role-build-spec .inline-icon { margin-right: 6px; }
select.build-spec-select { width: auto; max-width: 100%; min-height: 28px; padding: 0 26px 0 8px; font-size: .9375rem; }
select.build-spec-select.is-none { color: var(--text-muted); }
.build-note-more { display: inline-flex; align-items: center; justify-content: center; min-width: 28px; height: 28px; padding: 0 6px; border: 1px solid transparent; border-radius: 4px; background: none; color: var(--text-muted); font: inherit; font-size: 1.125rem; font-weight: 700; line-height: 1; cursor: pointer; }
.build-note-more:hover,
.build-note-more:focus-visible { border-color: var(--border); background: var(--raised); color: var(--text); }
.build-note { display: inline-flex; align-items: center; gap: 4px; max-width: 100%; }
.build-note-text { padding: 2px 6px; border: 1px solid transparent; border-radius: 4px; background: none; color: var(--text-muted); font: inherit; font-size: .9375rem; text-align: left; overflow-wrap: anywhere; cursor: pointer; }
.build-note-text:hover,
.build-note-text:focus-visible { border-color: var(--border); background: var(--raised); color: var(--text); }
.build-note-words::before { content: "“"; }
.build-note-words::after { content: "”"; }
.build-note-editing { display: flex; align-items: center; gap: 6px; width: 100%; max-width: 20em; }
.build-note-editing input[type=text].input-note { flex: 1 1 auto; min-width: 0; min-height: 32px; padding: 2px 8px; }
.role-build-note { font-size: .9375rem; }
.role-build-note::before { content: "“"; }
.role-build-note::after { content: "”"; }
[hidden].build-note-editing, [hidden].build-note-more, [hidden].build-note { display: none; }

/* A spec on the roster (7O): a badge on its role icon's upper right corner, half outside it, so the
   role's picture (the damage sword runs corner to corner) stays readable; a second spec in the main
   role, with no role icon of its own, as a small icon in the second role's place. With no icon file
   the spec's name shows in small words instead. */
.role-with-badge { position: relative; display: inline-flex; flex: none; margin-right: 8px; }
.spec-badge { position: absolute; right: -9px; top: -7px; display: inline-flex; }
.spec-badge-icon { border-radius: 3px; box-shadow: 0 0 0 2px var(--surface); }
.role-with-badge.is-main .spec-badge-icon { width: 20px; height: 20px; }
.role-with-badge.is-small .spec-badge-icon { width: 15px; height: 15px; border-radius: 2px; }
.spec-slot { display: inline-flex; flex: none; align-items: center; justify-content: center; width: 24px; height: 24px; }
.spec-slot .spec-icon { width: 100%; height: 100%; border-radius: 3px; }
.spec-slot:has(.spec-name-tag) { width: auto; }
.spec-name-tag { font-size: .75rem; color: var(--text-muted); white-space: nowrap; }
.role-with-badge .spec-name-tag { padding: 0 3px; border-radius: 3px; background: var(--raised); }

/* The character form's spec tiles (7O) and the Talent specs editor */
/* Two tidy lines a spec: the name, its roles, and Save; then how many chose it and the buttons */
.talent-spec-row .talent-spec-form { flex: 1 1 100%; }
.talent-spec-row .milestone-ticks { margin-left: 34px; margin-right: auto; }
.talent-spec-form { flex-wrap: wrap; align-items: center; }
.talent-spec-form > input[type=text] { flex: 0 1 200px; }
.talent-spec-form .spec-role-checks { flex: 1 1 auto; gap: 0 14px; }
.talent-spec-icon { display: inline-flex; width: 26px; }
.talent-spec-icon .inline-icon { width: 26px; height: 26px; margin: 0; vertical-align: 0; }
.spec-role-checks .check { min-height: 32px; gap: 6px; }
.talent-spec-no-icon { flex-basis: 100%; font-size: .875rem; }

.character-form > :last-child { margin-bottom: 0; }
.error-list { margin: 4px 0 0; padding-left: 20px; }

/* Game icons (served to logged-in members through /icon) */
.game-icon { display: block; flex: none; width: 40px; height: 40px; border-radius: 4px; border: 1px solid #000; }
.character-icon { width: 44px; height: 44px; }
.inline-icon { display: inline-block; width: 22px; height: 22px; margin-right: 4px; vertical-align: -6px; border-radius: 3px; }
.icon-label { display: inline-block; margin: 0 10px 2px 0; white-space: nowrap; }

/* Choice tiles: a hidden radio button or checkbox followed by .tile-body.
   Tiles with an icon show only the icon; the name stays for screen readers
   and the hover title, and the "Chosen:" line under the group spells it out. */
.tile-grid { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 6px; max-width: 360px; margin-top: 6px; }
.tile { position: relative; }
.tile-input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.tile-input:disabled { cursor: not-allowed; }
.tile-body {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  min-height: 56px;
  padding: 5px 2px;
  font-size: .75rem;
  line-height: 1.2;
  text-align: center;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.tile-body .game-icon { width: 44px; height: 44px; }
.tile-name { max-width: 100%; font-weight: 700; overflow-wrap: break-word; }
.tile-body.has-icon .tile-name,
.tile-note {
  position: absolute !important;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}
.tile:hover .tile-body { border-color: var(--text-muted); }
.tile-input:focus-visible + .tile-body { outline: 2px solid var(--red-text); outline-offset: 2px; }
.tile-input:checked + .tile-body {
  background: var(--raised);
  border-color: var(--red-text);
  box-shadow: inset 0 0 0 1px var(--red-text);
}
/* A check mark in the corner, so the choice doesn't rest on color alone */
.tile-input:checked + .tile-body::after {
  content: "✓";
  position: absolute;
  top: -6px;
  right: -6px;
  display: grid;
  place-items: center;
  width: 18px;
  height: 18px;
  font-size: .75rem;
  font-weight: 700;
  color: var(--text);
  background: var(--red-fill);
  border-radius: 50%;
}
.tile.is-unavailable .tile-input:not(:checked) + .tile-body > * { opacity: .4; }
.tile.is-unavailable .tile-body { border-style: dashed; }
.tile-readout { margin: 8px 0 0; font-size: .9375rem; color: var(--text-muted); }
.tile-readout strong { color: var(--text); }


/* --------------------------------------------------------------------------
   Roster: compact, since officers scan it. One line per character on
   desktop; on phones each line wraps instead of scrolling sideways.
   -------------------------------------------------------------------------- */

.back-link { margin: 0 0 8px; }

/* Filter menus in one row (two per row on phones), with no visible labels:
   the first choice of each names it. A menu that is set gets a red outline. */
.roster-controls { margin-bottom: 12px; }
.roster-filters { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; padding: 10px; }
@media (min-width: 760px) {
  .roster-filters { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (max-width: 359px) {
  .roster-filters { grid-template-columns: minmax(0, 1fr); }
}
.roster-filters select.is-set { border-color: var(--red-text); }

/* Under the menus: the count on the left, Mains only and Sort by on the right */
.roster-toolbar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0 16px; margin-top: 6px; }
.roster-count { margin: 0; color: var(--text-muted); }
.roster-view-options { display: flex; flex-wrap: wrap; align-items: center; gap: 0 16px; }
.roster-sort { display: flex; align-items: center; gap: 8px; }
.roster-sort label { font-weight: 700; white-space: nowrap; }
.roster-sort select { width: auto; }

.roster { display: grid; gap: 10px; margin: 0; padding: 0; list-style: none; }
.roster-member {
  padding: 10px 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.roster-member-heading { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 10px; }
.roster-member-heading h2 { margin: 0; font-size: 1.5rem; overflow-wrap: break-word; }
/* The Discord name after Discord's mark: cut at a width with the whole name
   on hover, and a press shows it all (reveal.js) for touch (5I). A plain
   button so the keyboard reaches it; it looks like the muted text it replaced. */
.roster-discord { display: inline-flex; align-items: center; gap: 5px; max-width: 100%; margin: 0; padding: 0; border: 0; background: none; font: inherit; color: var(--text-muted); cursor: default; }
.roster-discord .icon { flex: none; width: 16px; height: 16px; }
.roster-discord-name { max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.roster-discord.is-cut { cursor: pointer; }
.roster-discord.is-cut:hover .roster-discord-name { color: var(--text); }
.roster-discord.is-open .roster-discord-name { max-width: none; white-space: normal; overflow-wrap: anywhere; }
.roster-manage { margin-left: auto; font-size: .9375rem; }
.roster-empty { margin: 4px 0 0; }

/* One line per character: race and class icons with the name, roles, primary
   professions, and secondary professions in columns, so each kind lines up
   down the list. Sized for reading on a desktop monitor, with room for a
   first name and a surname at their longest, so the lines keep an even
   height. The name column narrows first when space is short. Below 760px the
   line is two rows: the name with the level at its far end, then the roles,
   professions, and secondary professions in the same columns as above, so
   they still line up down the list (the icons a step smaller below 360px,
   where a row of them wouldn't fit). */
.roster-characters { margin: 6px 0 0; padding: 0; list-style: none; }
.roster-character {
  display: grid;
  grid-template-columns: auto auto minmax(0, 1fr) auto;
  grid-template-areas:
    "name  name name level"
    "roles prof sec  .";
  align-items: center;
  gap: 4px 12px;
  padding: 7px 0;
  border-top: 1px solid var(--border);
}
.roster-character > * { min-width: 0; }
.roster-name { grid-area: name; display: flex; align-items: center; gap: 10px; font-size: 1.125rem; overflow-wrap: break-word; }
.roster-level { grid-area: level; }
.roster-roles { grid-area: roles; }
.roster-professions { grid-area: prof; }
.roster-secondary { grid-area: sec; justify-self: start; }
.roster-name .main-star .icon { width: 18px; height: 18px; }
.roster-icon { width: 34px; height: 34px; border-radius: 4px; }
/* Race and class icons as a pair before the name ("Tauren Druid" on hover) */
.roster-kind { display: inline-flex; flex: none; align-items: center; gap: 4px; }
.roster-kind-name { font-size: .875rem; color: var(--text-muted); }
@media (min-width: 760px) {
  .roster-character {
    grid-template-columns: minmax(0, 330px) 40px 96px 68px minmax(120px, 1fr);
    grid-template-areas: "name level roles prof sec";
    gap: 4px 16px;
  }
}
/* The level's narrow column (5A), its place held: a number, or a quiet dash
   for a level nobody has filled in. */
.roster-level { flex: none; min-width: 32px; font-weight: 700; text-align: right; padding-right: 10px; cursor: default; }
.roster-level.is-unknown { font-weight: 400; color: var(--text-muted); }

/* Icons only: the main role larger than the second role */
.roster-roles,
.roster-professions,
.roster-secondary { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; }
.roster-roles { gap: 6px; }
.roster-glyph { display: inline-flex; align-items: center; }
.roster-glyph .game-icon { display: block; }
.roster-glyph-main { width: 36px; height: 36px; border-radius: 4px; }
.roster-glyph-small { width: 24px; height: 24px; border-radius: 3px; }
.roster-glyph-prof { width: 32px; height: 32px; border-radius: 4px; }
/* The second role's place, held when there isn't one (second_role_slot()), so
   one-role characters line up with the rest: on the roster, the heatmap's
   list, and an event's signups. Two professions' room is held the same way
   where the roster's line wraps and no grid column does it. */
.role-slot { display: inline-flex; flex: none; width: 24px; height: 24px; }
.roster-professions { min-width: 68px; }

/* A thin line between primary and secondary professions, on every line so
   it reads as a column edge. Each secondary profession has a fixed slot, and
   an empty slot keeps the space. */
.roster-secondary { position: relative; flex-wrap: nowrap; min-height: 32px; padding-left: 14px; }
.roster-slot { flex: none; width: 32px; height: 32px; }
.roster-secondary::before {
  content: "";
  position: absolute;
  top: 4px;
  bottom: 4px;
  left: 0;
  width: 1px;
  background: var(--border);
}
@media (max-width: 359px) {
  .roster-glyph-main { width: 32px; height: 32px; }
  .roster-glyph-small, .role-slot { width: 22px; height: 22px; }
  .roster-glyph-prof, .roster-slot { width: 28px; height: 28px; }
  .roster-professions { min-width: 60px; }
  .roster-secondary { min-height: 28px; }
}


/* --------------------------------------------------------------------------
   Accounts and the action log (officers and admins). Compact lists like the
   roster. Each account is a small grid: on phones the buttons sit below the
   name; above 760px they move to the right, with History always last.
   -------------------------------------------------------------------------- */

.account-section { margin-top: 24px; }
.account-section > h2 { margin-bottom: 4px; font-size: 1.5rem; }
.account-section > h2 .muted { font: 400 1rem var(--font-body); }

.account-list { display: grid; gap: 10px; margin: 12px 0 0; padding: 0; list-style: none; }
.account {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas:
    "heading history"
    "meta    meta"
    "overdue overdue"
    "onote   onote"
    "actions actions";
  column-gap: 16px;
  padding: 10px 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.account.is-deactivated { border-style: dashed; }
.account-heading { grid-area: heading; display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 10px; }
.account-heading h3 { margin: 0; font-size: 1.3rem; overflow-wrap: anywhere; }
.account-history { grid-area: history; align-self: baseline; font-size: .9375rem; }
.account-meta { grid-area: meta; display: flex; flex-wrap: wrap; align-items: center; gap: 2px 14px; margin: 2px 0 0; color: var(--text-muted); }
.account-main { display: inline-flex; align-items: center; font-weight: 700; }
.account-overdue { grid-area: overdue; display: flex; gap: 6px; align-items: center; margin: 6px 0 0; color: var(--warning); }
.account-actions { grid-area: actions; display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
/* Login links (7R): the officer's page, and its way in on Accounts. */
.account-login-link { margin: 0 0 16px; }
.login-link-page input[type=text].input-link { width: 100%; font-variant-numeric: tabular-nums; }
.login-link-matches { list-style: none; margin: 16px 0; padding: 0; }
.login-link-matches li { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; padding: 8px 0; border-top: 1px solid var(--border); }
.login-link-matches li .btn { margin-left: auto; }
@media (min-width: 760px) {
  .account {
    grid-template-columns: minmax(0, 1fr) auto auto;
    grid-template-areas:
      "heading actions history"
      "meta    actions history"
      "overdue actions history"
      "onote   onote   onote";
  }
  .account-history { align-self: center; }
  .account-actions { align-self: center; margin-top: 0; }
}

/* The officer note (7D.2): under the name, the words (a button for whoever
   may change them), then "Last changed by …" small and muted; the box and
   its hint replace the words while editing. Read-only on the confirmations. */
.account .officer-note { grid-area: onote; }
.officer-note { margin: 6px 0 0; line-height: 1.5; }
.officer-note .note-text { display: inline-flex; align-items: flex-start; gap: 4px; margin-left: -6px; text-align: left; }
.officer-note .note-text .icon { flex: none; margin: 3px 0 0; }
.officer-note .note-text,
.officer-note-words,
.officer-note-read .icon,
.officer-note .note-text .icon { color: var(--officer); }
.officer-note.is-empty .note-text,
.officer-note.is-empty .note-text .icon { color: var(--text-muted); }
.officer-note.is-empty [data-onote-text] { text-decoration: underline; text-underline-offset: 3px; }
.officer-note-read { display: flex; gap: 4px; margin: 0; overflow-wrap: anywhere; }
.officer-note-read .icon { flex: none; width: 18px; height: 18px; margin-top: 3px; }
.officer-note-changed { display: block; font-size: .875rem; color: var(--text-muted); }
.officer-note-changed { padding-left: 22px; }
[hidden].officer-note-changed, [hidden].officer-note-editing { display: none; }
.officer-note-editing { margin-top: 2px; }
.officer-note-editing .note-editing { align-items: flex-start; }
.officer-note-editing textarea.input-officer-note { flex: 1 1 auto; min-width: 0; min-height: 0; padding: 4px 8px; resize: vertical; }
.officer-note-hint { margin: 4px 0 0; font-size: .875rem; color: var(--text-muted); }
.officer-note-box { margin: 0 0 16px; padding: 8px 12px; background: var(--raised); border: 1px solid color-mix(in srgb, var(--officer), var(--border) 70%); border-radius: var(--radius); }

/* Characters named on the confirmation pages (ul. to outweigh .confirm-panel ul) */
ul.account-characters { display: flex; flex-wrap: wrap; gap: 6px 18px; margin: 0 0 16px; padding: 0; list-style: none; }
.account-characters li { display: inline-flex; align-items: center; gap: 4px; font-weight: 700; }

/* The log: time, then a sentence, detail, and reason. Side by side above 760px. */
.log-list { margin: 16px 0 0; padding: 0; list-style: none; }
.log-entry { display: grid; gap: 2px 16px; padding: 10px 0; border-top: 1px solid var(--border); }
.log-entry:last-child { border-bottom: 1px solid var(--border); }
@media (min-width: 760px) {
  .log-entry { grid-template-columns: 190px minmax(0, 1fr); }
}
.log-time { font-size: .9375rem; color: var(--text-muted); }
.log-body > p { margin: 0; overflow-wrap: anywhere; }
.log-detail { color: var(--text-muted); }
/* Admin → Recent errors (7Q.3): the action log's list, the error's own words in a fixed-width face so they read as quoted */
.error-what { font: .875rem/1.5 ui-monospace, "SF Mono", Menlo, Consolas, monospace; color: var(--text); }
.error-list .log-detail { font-size: .875rem; }
.log-pages { margin-top: 16px; }

/* Mains per role (roster heading and home page): a small box per role with
   its icon and count of mains, and under it, centered, a "+N" for mains who
   can fill the role as their second role. The boxes share one width. */
.role-summary { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; }
.role-summary ul { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 8px; margin: 0; padding: 0; list-style: none; }
.role-summary a {
  display: grid;
  grid-template-columns: auto auto;
  justify-content: center;
  align-items: center;
  gap: 2px 8px;
  height: 100%;
  padding: 6px 14px 4px;
  color: var(--text);
  text-decoration: none;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.role-summary a:hover { border-color: var(--text-muted); }
.role-summary .game-icon { width: 36px; height: 36px; border-radius: 4px; }
.role-summary-count { font-size: 1.625rem; line-height: 1; }
.role-summary-flex { grid-column: 1 / -1; justify-self: center; font-size: .8125rem; line-height: 1.2; color: var(--text-muted); }
/* Inside a panel the boxes sit a step lower, like the character form's tiles */
.panel .role-summary a { background: var(--bg); }

/* Your own entry on the roster (first in the default order) and the Accounts
   page (always first): a red edge, like the current page in the phone menu.
   Screen readers hear "(you)" after the name. */
.roster-member.is-you,
.account.is-you {
  border-color: color-mix(in srgb, var(--red-text), transparent 55%);
  box-shadow: inset 3px 0 0 var(--red-text);
}


/* --------------------------------------------------------------------------
   Bands: a textured strip under the header holding a framed introduction,
   on the public page (the guild) and the home page (the greeting). Pages
   with a band are full width and lay out their own .wrap sections.
   -------------------------------------------------------------------------- */

.page-full { padding-bottom: 24px; }
.page-full-flash { padding-top: 16px; }

.band {
  padding: 40px 0;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}
.band-compact { padding: 24px 0; }
.hero-frame h1 { margin-bottom: .1em; font-size: clamp(2rem, 7vw, 3rem); overflow-wrap: anywhere; }

/* Under the frame's heading: "Horde · PvE", or your tier */
.band-subline {
  margin-bottom: 1.25em;
  font-size: .875rem;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.hero-frame .divider { margin: 24px 0 20px; }

/* Recruiting status: the words carry the meaning; the icon repeats it */
.pill.is-open .icon { color: var(--success); }
.pill.is-closed .icon { color: var(--text-muted); }

/* Public page */
.public-preview-note { margin: 0; padding: 12px 0; text-align: center; color: var(--text-muted); }
.emblem { display: block; width: 88px; height: 88px; margin: 0 auto 6px; color: var(--red-text); }
.public-note { max-width: 32em; margin-left: auto; margin-right: auto; }
.public-actions { justify-content: center; margin-top: 20px; }
.public-newcomers { max-width: 30em; margin: 16px auto 0; font-size: .9375rem; color: var(--text-muted); }

/* Home page: the band holds the greeting about your main (race, class, and
   role icons, your rank, then your other characters and Manage characters,
   and a line about your week when it needs you) beside the guild; the
   heatmap follows */
.home-greeting { padding: 20px; }
.home-greeting h1 { font-size: clamp(1.75rem, 5.5vw, 2.5rem); }
/* The name stays whole: on its own line under "Welcome back," when the two don't fit together (5I) */
.home-greeting-name { white-space: nowrap; }
.home-greeting-kind { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 6px; margin: 10px 0 8px; }
.home-greeting-rank { margin-left: 10px; font-size: .875rem; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--text-muted); }
.home-greeting-more { margin: 0; color: var(--text-muted); }
.home-greeting-more [title] { cursor: default; }
/* Your week, only when it needs you: not filled in yet, or not confirmed for a while */
.home-greeting-week { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 8px 12px; margin-top: 14px; }
.home-greeting-week form { margin: 0; }
.home-actions { margin: 16px 0 0; }
/* Side by side above 1024px in matching frames of one height, each box
   centering its lines top to bottom; narrower, they stack at the frame's
   usual width */
.home-band { display: grid; gap: 16px; }
.home-band > .hero-frame { display: flex; flex-direction: column; justify-content: center; width: 100%; }
.home-band-content > :last-child { margin-bottom: 0; }
@media (min-width: 1024px) {
  .home-band { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .home-band > .hero-frame { max-width: none; margin: 0; }
  /* A step smaller, so "Welcome back," and a wide 12-letter name share one line */
  .home-band .home-greeting h1 { font-size: 2.125rem; }
}
/* The guild: role counts, then the member count beside recruiting, then the note */
.home-band-guild { padding: 20px; }
.home-band-counts { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 6px 12px; margin-bottom: 12px; }
/* With the Up for grabs tile too (7T), five tiles share one row: tighter padding and gaps, in the band only */
.home-band-counts.has-offers { gap: 6px 8px; }
.home-band-counts.has-offers .role-summary ul { gap: 6px; }
.home-band-counts.has-offers .role-summary a { gap: 2px 6px; padding: 6px 9px 4px; }
.home-band-counts.has-offers .profession-tile { padding: 6px 9px 4px; }
.home-band-guild .role-summary { justify-content: center; }
.home-band-status { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 8px 16px; margin-bottom: 8px; }
.home-band-status strong { font-size: 1.25rem; line-height: 1; }
.home-band-note { overflow-wrap: anywhere; }

@media (max-width: 479px) {
  .band { padding: 24px 0; }
  .band-compact { padding: 16px 0; }
  .hero-frame { padding: 24px 16px; }
  .home-greeting, .home-band-guild { padding: 16px; }
  .emblem { width: 72px; height: 72px; }
  .public-actions .btn { flex: 1 1 100%; }
}


/* --------------------------------------------------------------------------
   Events (the Events page, an event's page, and the planning form). Lists
   are compact like the roster; an event's signups sit in three role columns.
   Coming and Maybe always carry an icon and a word as well as a style.
   -------------------------------------------------------------------------- */

.events-zone { margin: -4px 0 20px; color: var(--text-muted); }
.events-empty { margin-bottom: 20px; }

.event-section + .event-section { margin-top: 24px; }
.event-section-title { margin: 0 0 8px; font: 700 .8125rem/1.3 var(--font-body); letter-spacing: .1em; text-transform: uppercase; color: var(--text-muted); }
.event-section .hint { margin: 8px 0 0; }

/* One line per event, linking to its page */
.event-lines { margin: 0; padding: 0; list-style: none; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; }
.event-line {
  display: grid;
  gap: 4px 18px;
  align-items: center;
  padding: 10px 14px;
  color: var(--text);
  text-decoration: none;
}
.event-lines li + li .event-line { border-top: 1px solid var(--border); }
.event-line:hover { background: var(--raised); }
@media (min-width: 760px) {
  /* The counts column has one width on every line, so the stacks line up
     down the list (each line is its own grid); the title takes the rest */
  .event-line { grid-template-columns: 170px minmax(200px, 1fr) 320px 170px; }
}
/* Events you've signed up for: the red left edge, as on the roster (5C drew a red line all the
   way round too; 5K dropped it, since the pill and the character under it already say it) */
.event-line.is-you { box-shadow: inset 4px 0 0 var(--red-text); }
/* All events, or only yours */
.events-show { display: flex; gap: 4px; margin: 0 0 16px; }
.events-show a { padding: 6px 12px; color: var(--text-muted); text-decoration: none; border-radius: var(--radius); }
.events-show a:hover { color: var(--text); background: var(--surface); }
.events-show a[aria-current] { color: var(--text); background: var(--raised); box-shadow: inset 0 -2px 0 var(--red-text); }
.event-line.is-cancelled .event-name strong { color: var(--text-muted); text-decoration: line-through; }
.event-section.is-ended .event-name strong { color: var(--text-muted); }
.event-when strong { display: block; }
.event-time { color: var(--text-muted); }
.event-after-midnight { font-size: .875rem; }
.event-kind { display: block; margin: 0; font-size: .75rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--text-muted); }
.event-name { min-width: 0; }
.event-name strong { display: block; font-size: 1.125rem; overflow-wrap: anywhere; }
/* What the event needs, under the title (5K): the key and the name, in the range's quiet style */
.event-line-needs { display: block; margin-top: 2px; font-size: .875rem; color: var(--text-muted); }
.event-line-needs .icon { width: 15px; height: 15px; vertical-align: -3px; margin-right: 2px; color: var(--text); }
/* Who's coming, one line each: the role icons with counts, "Still need", then
   the count of people (the testers found them hard to read on one line) */
.event-counts { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; color: var(--text-muted); }
@media (min-width: 760px) {
  .event-counts { align-items: center; text-align: center; }
}
.event-role-counts { display: inline-flex; gap: 10px; }
.event-role-count { display: inline-flex; align-items: center; gap: 5px; font-weight: 700; color: var(--text); }
/* "Still need" wraps as text, breaking only between roles: the icon stays with the label and each role keeps its words */
.event-needed { display: inline; color: var(--text); }
.event-needed-label, .event-needed-part { white-space: nowrap; }
.event-needed .icon { vertical-align: -3px; margin-right: 2px; color: var(--success); }
.event-needed.is-short .icon { color: var(--warning); }
.event-status { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; }
@media (min-width: 760px) {
  .event-status { align-items: flex-end; }
}
/* Which character you signed up with, under the pill (5K): "as", the class icon, the name in
   class color, and the key when the event needs something that character has */
.event-signup-as { display: block; max-width: 100%; font-size: .875rem; line-height: 1.4; color: var(--text-muted); overflow-wrap: break-word; }
@media (min-width: 760px) {
  .event-signup-as { text-align: right; }
}
.event-signup-as-lead, .event-signup-as-tail { white-space: nowrap; }
.event-signup-as .roster-glyph-small { display: inline-block; width: 20px; height: 20px; vertical-align: -5px; margin: 0 1px; }
.event-signup-as-key .icon { width: 15px; height: 15px; vertical-align: -3px; margin-left: 2px; color: var(--text); }
/* "Sign up" on a line reads as a link: the line opens the event page (5K; it was drawn as a button) */
.event-signup-link { color: var(--red-text); text-decoration: underline; text-underline-offset: 3px; }
.event-line:hover .event-signup-link { color: var(--text); }
.heat-event-status { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }

/* Your status on a list line: Coming is solid, Maybe dashed, each with its icon */
.pill.is-coming { font-weight: 700; border-color: var(--text-muted); }
.pill.is-coming .icon { color: var(--success); }
.pill.is-maybe { border-style: dashed; border-color: var(--text-muted); }
.pill.is-cancelled { color: var(--text-muted); }
.pill.is-asked { border-color: var(--warning); }
.pill.is-asked .icon { color: var(--warning); }

/* An event's page */
.event-head { margin-bottom: 20px; }
.event-head h1 { margin: 0; overflow-wrap: anywhere; }
.event-meta { display: flex; flex-wrap: wrap; gap: 2px 16px; margin: 4px 0 0; color: var(--text-muted); }
.event-meta strong { color: var(--text); }
/* Copy to another date: the rarest action, a quiet link among the facts (5J) */
.event-copy { color: var(--text-muted); text-decoration-color: var(--border); }
.event-copy:hover { color: var(--text); }
/* The description runs the width of the signup box below it (7Q; 65 characters until then, which wrapped early) */
.event-description { margin: 10px 0 0; overflow-wrap: break-word; }
.event-description .text-link { overflow-wrap: anywhere; }
.event-tools { margin-top: 14px; gap: 8px; }
.event-tools form { margin: 0; }
/* Edit first and a little stronger; Cancel event alone at the far right (5J) */
.event-edit { background: var(--raised); border-color: var(--text-muted); }
.event-edit:hover { background: var(--surface); }
.event-cancel { margin-left: auto; }

.alert-quiet { border-color: var(--text-muted); }
.alert-quiet > .icon { color: var(--text-muted); }
.alert-quiet p { margin: 0; }
.alert-quiet form { margin-top: 10px; }

/* Your signup */
.signup-box { margin-bottom: 16px; }
.signup-box-heading { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 16px; margin-bottom: 12px; }
.signup-box-heading h2 { margin: 0; font-size: 1.5rem; }
/* Your status beside the heading, once you're signed up: the Events page's pill (5J) */
.signup-state { margin: 0; }
.signup-save { margin: 0; font-size: .9375rem; color: var(--text-muted); }
.signup-save.is-error { display: inline-flex; color: var(--danger); }
.signup-note { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; margin: 0; }
.signup-prompt { display: grid; gap: 10px; margin-bottom: 14px; padding: 10px 14px; border: 1px solid var(--warning); border-radius: var(--radius); }
.signup-prompt p { margin: 0; }
.signup-prompt .icon { color: var(--warning); }
/* Away that day: a quiet hint only you see */
.signup-away { display: flex; align-items: baseline; gap: 8px; margin: 0 0 14px; color: var(--text-muted); }
.signup-away .icon { align-self: center; }
.signup-choices { display: grid; gap: 10px; margin-bottom: 14px; }
.signup-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; }
/* One label column for every row, and the "Or I could come on…" picks sit in from it (7A, 7Q) */
.signup-label { width: 100px; font-weight: 700; color: var(--text-muted); }
.signup-label-flex { width: auto; margin-left: 18px; }
.signup-picks { display: flex; flex-wrap: wrap; gap: 8px; }

/* A choice button: pressed gets the red outline and a check, like the character form's tiles */
.pick {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: var(--tap);
  padding: 4px 12px 4px 6px;
  font: inherit;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  cursor: pointer;
}
.pick:hover { border-color: var(--text-muted); }
.pick[aria-pressed="true"] { background: var(--raised); border-color: var(--red-text); box-shadow: inset 0 0 0 1px var(--red-text); }
.pick[aria-pressed="true"]::after {
  content: "✓";
  position: absolute;
  top: -7px;
  right: -7px;
  display: grid;
  place-items: center;
  width: 18px;
  height: 18px;
  font-size: .75rem;
  font-weight: 700;
  color: var(--text);
  background: var(--red-fill);
  border-radius: 50%;
}
.pick:disabled { cursor: not-allowed; border-style: dashed; }
.pick:disabled > * { opacity: .35; }
.pick-icon { width: 30px; height: 30px; border-radius: 3px; }
.pick-name { font-weight: 700; }
.pick-role { padding: 4px; }
.pick-role-icon { width: 34px; height: 34px; border-radius: 3px; }

.signup-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; }
.signup-status { justify-content: center; min-width: 130px; padding: 8px 16px; font-weight: 700; }
.signup-status .icon { width: 20px; height: 20px; }
.signup-status.is-maybe { border-style: dashed; }
/* Withdraw in the same shape, once you're signed up (5J); it's an action, never pressed */
.signup-withdraw { color: var(--text-muted); }
.signup-withdraw .icon { color: var(--danger); }
.signup-withdraw:hover { color: var(--text); }

/* Everyone signed up */
.signups-heading { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 16px; margin-bottom: 12px; }
.signups-heading h2 { margin: 0; font-size: 1.5rem; }
.signups-count { margin: 0; color: var(--text-muted); }
.signups-none { margin: 0; }
/* A raid's classes (7S): every class with the number coming, a class with
   nobody dimmed at 0; the maybes are in each one's words */
.signup-classes { display: flex; flex-wrap: wrap; gap: 4px 14px; margin: -4px 0 14px; padding: 0; list-style: none; }
.signup-class { display: inline-flex; align-items: center; gap: 5px; color: var(--text-muted); font-size: .875rem; }
.signup-class .signup-class-icon { width: 20px; height: 20px; border-radius: 3px; }
.signup-class.is-none { opacity: .45; }

.signup-columns { display: grid; gap: 16px 20px; }
@media (min-width: 760px) {
  .signup-columns { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
/* Each column's heading carries its count ("1 of 1" when the event wants 1,
   amber and dashed while short) and, when someone coming in another role
   could switch into it, the game's swap mark with how many (5J) */
.signup-group-title { display: flex; align-items: center; gap: 10px; margin: 0 0 4px; padding-bottom: 4px; font: 700 .9375rem/1.3 var(--font-body); color: var(--text-muted); border-bottom: 1px solid transparent; }
.signup-group-title.is-short { border-bottom-color: var(--warning); border-bottom-style: dashed; }
.signup-group-name { display: inline-flex; align-items: center; gap: 8px; }
.signup-group-title .game-icon { width: 20px; height: 20px; border-radius: 3px; }
.signup-group-count { color: var(--text); }
.signup-group-title.is-short .signup-group-count { color: var(--warning); }
.signup-group-switch { display: inline-flex; align-items: center; gap: 4px; margin-left: auto; font-weight: 700; color: var(--text); cursor: default; }
.signup-switch-icon { width: 22px; height: 22px; border-radius: 3px; }
.signup-people { margin: 0; padding: 0; list-style: none; }
/* The maybes, after the people coming, below a dashed line */
.signup-people.is-after { margin-top: 8px; padding-top: 6px; border-top: 1px dashed var(--text-muted); }
.signup-person { display: grid; padding: 3px 8px; border-top: 1px solid var(--border); }
/* min-width: 0 lets the line shrink to its column, so a long name wraps
   (5I) instead of the line spilling into the next column */
.signup-person-main { display: flex; align-items: center; gap: 8px; min-width: 0; min-height: 32px; }
.signup-people.is-after .signup-person:first-child { border-top: 0; }
.signup-person:last-child { border-bottom: 1px solid var(--border); }
.signup-person.is-you { box-shadow: inset 3px 0 0 var(--red-text); }
.signup-person-kind { display: inline-flex; flex: none; gap: 3px; }
.signup-icon { width: 26px; height: 26px; border-radius: 3px; }
/* A name short of room wraps between its two parts rather than being cut
   short (5I); break-word keeps a single part whole */
.signup-person-name { min-width: 0; font-size: 1.0625rem; line-height: 1.2; overflow-wrap: break-word; }
.signup-person.is-maybe .signup-person-name { font-weight: 400; }
/* The character's level after the name (5A; not on raids), a dash when it isn't filled in */
.signup-person-level { flex: none; min-width: 22px; font-weight: 700; text-align: right; color: var(--text-muted); cursor: default; }
.signup-person-level.is-unknown { font-weight: 400; }
.pick-level { color: var(--text-muted); }
.signup-mark { display: inline-flex; flex: none; color: var(--warning); }
.signup-mark .icon { width: 18px; height: 18px; }
/* The "can also" role is the line's last column, its place held when empty */
.signup-person .role-slot { margin-left: auto; }
.signup-maybe + .role-slot { margin-left: 0; }
/* Another character the person could come on (7Q; 5E's alt): a second line under them, "or", its role, its spec or class icon, and its name */
.signup-person-alt { display: inline-flex; margin: -2px 0 2px 34px; font-size: .875rem; color: var(--text-muted); cursor: default; }
.signup-person-alt-shown { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 4px; }
.signup-person-alt .roster-glyph-small { width: 20px; height: 20px; border-radius: 3px; }
.signup-person-alt-level { font-weight: 700; }
.signup-person-alt-level.is-unknown { font-weight: 400; }
/* "Or I could come on…" in Your signup (7Q): a box, unticked until wanted, then your other characters and a role, a size down from the rows above */
.signup-alt { display: grid; gap: 8px; }
.signup-alt-check { width: fit-content; min-height: 32px; font-weight: 700; color: var(--text-muted); cursor: pointer; }
.signup-alt-check input { width: 20px; height: 20px; cursor: pointer; }
.signup-alt-check:has(input:checked) { color: var(--text); }
.pick-alt { min-height: 36px; padding: 3px 10px 3px 5px; }
.pick-alt .pick-icon { width: 24px; height: 24px; }
.pick-alt-role .pick-role-icon { width: 26px; height: 26px; }
@media (max-width: 559px) {
  .signup-alt-row > .signup-label:first-child { display: none; }
}
/* A maybe is its dashed question mark alone, "Maybe" on hover (5I) */
.signup-maybe { display: inline-flex; flex: none; align-items: center; margin-left: auto; color: var(--text-muted); cursor: default; }
.signup-maybe .icon { width: 20px; height: 20px; }
.signup-empty { margin: 0; padding: 7px 8px; color: var(--text-muted); border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); }
/* An "other" event: everyone in one run of columns */
.signup-flat .signup-people { display: grid; column-gap: 20px; }
@media (min-width: 760px) {
  .signup-flat .signup-people { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* Planning an event: a wider form than the site's other forms (5J), since
   events are planned at a monitor; thin rules between what, when, and details */
.narrow-event { max-width: 680px; }
.event-form-rule { margin: 4px 0 18px; border: 0; border-top: 1px solid var(--border); }
.event-details-row { display: flex; flex-wrap: wrap; gap: 0 40px; }
.event-details-row .field { margin-bottom: 4px; }
.event-details-hint { margin: 0 0 16px; }
.event-kinds { display: grid; gap: 8px; margin-top: 6px; }
@media (min-width: 560px) {
  /* Three tiles for officers and admins, two for members, sharing the width either way. */
  .event-kinds { grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); }
}
.event-kind-choice { position: relative; display: flex; }
.event-kind-choice input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.event-kind-body {
  display: grid;
  align-content: start;
  gap: 2px;
  width: 100%;
  padding: 10px 12px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.event-kind-body span { font-size: .875rem; line-height: 1.35; color: var(--text-muted); }
.event-kind-choice:hover .event-kind-body { border-color: var(--text-muted); }
.event-kind-choice input:checked + .event-kind-body { background: var(--raised); border-color: var(--red-text); box-shadow: inset 0 0 0 1px var(--red-text); }
.event-kind-choice input:checked + .event-kind-body::after {
  content: "✓";
  position: absolute;
  top: -7px;
  right: -7px;
  display: grid;
  place-items: center;
  width: 18px;
  height: 18px;
  font-size: .75rem;
  font-weight: 700;
  color: var(--text);
  background: var(--red-fill);
  border-radius: 50%;
}
.event-kind-choice input:focus-visible + .event-kind-body { outline: 2px solid var(--red-text); outline-offset: 2px; }
.event-raid-size select { max-width: 200px; }
/* The roles an event wants: a role icon and a small number box for each. */
.event-asks-roles .hint { display: block; }
.event-wanted-counts { display: flex; flex-wrap: wrap; gap: 8px 20px; margin: 6px 0; }
.event-wanted-count { display: flex; align-items: center; gap: 8px; margin: 0; }
.event-wanted-icon { width: 28px; height: 28px; }
/* input[type=text] is full width; a count needs room for two digits */
input[type=text].input-wanted { width: 3.5rem; text-align: center; }

/* A level range: two small boxes with "to" between them (the planning form and the dungeons editor, 5D). */
input[type=text].input-range { width: 3.5rem; flex: none; text-align: center; }
.event-level-range, .dungeon-levels { display: flex; align-items: center; gap: 8px; }
.event-level-range { margin: 6px 0; }
.dungeon-item { flex-wrap: wrap; align-items: center; }
.dungeon-item > input[type=text]:not(.input-range) { flex: 1 1 220px; }
.event-when-fields { display: grid; gap: 0 12px; }
@media (min-width: 560px) {
  .event-when-fields { grid-template-columns: 1fr 1.75fr .7fr; }   /* Start holds − and + too (7B) */
}
.event-zone-hint { margin: -6px 0 16px; }
/* Start's − and + (7B): square buttons of the menu's height, just after it. */
.start-stepper { display: flex; gap: 4px; }
.start-stepper select { flex: 1 1 auto; min-width: 0; }
.start-step { flex: 0 0 auto; width: var(--tap); min-height: var(--tap); padding: 0; border: 1px solid var(--border); border-radius: var(--radius); background: var(--raised); color: var(--text); font: inherit; font-size: 1.25rem; font-weight: 700; line-height: 1; cursor: pointer; touch-action: manipulation; }
.start-step:hover:not(:disabled),
.start-step:focus-visible { border-color: var(--red-text); color: var(--red-text); }
.start-step:disabled { opacity: .4; cursor: default; }
.event-form .alert-quiet { align-items: center; }


/* --------------------------------------------------------------------------
   Noteworthy recipes (5H): on each My characters card, a group per
   profession (its icon and name open the profession's page) with the
   character's recipes as chips and an "Add a recipe" box whose pick list
   drops down from it; and the profession's page, with a strip of every
   profession's icon, everyone with the profession ("Alchemists", 7G), then
   "Recipes": a filter box and the recipes with who knows them.
   -------------------------------------------------------------------------- */
.character-recipes { display: grid; gap: 12px; margin: 0 0 16px; }
.recipe-group { margin: 0; }
.recipe-profession { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; margin: 0 0 6px; font-size: 1.0625rem; }
.recipe-profession a { display: inline-flex; align-items: center; color: inherit; text-decoration: none; }
.recipe-profession a:hover,
.recipe-profession a:focus-visible { color: var(--red-text); text-decoration: underline; }
.recipe-profession .inline-icon { vertical-align: middle; margin-right: 8px; }
/* "Alchemy · 17" once a card's list collapses (7C.2), open or closed */
.recipe-heading-count { color: var(--text-muted); font-family: var(--font-body); font-size: .9375rem; font-weight: 400; }

/* A profession's specialization and Maxed (7M), in the heading row on My characters */
.recipe-heading-row { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; margin: 0 0 6px; }
.recipe-heading-row .recipe-profession { margin: 0; }
/* "Max" sits beside the profession's name, the menu after it (7O, Alex's word): the status's pieces join the
   heading row itself, so the menu wraps under the name when there's no room and "Max" never leaves it */
.profession-status { display: contents; }
.profession-status select.profession-spec-select { flex: 0 1 auto; min-width: 0; text-overflow: ellipsis; }
.profession-status .profession-maxed-toggle { flex: none; }
.profession-spec { color: var(--text-muted); font-size: .9375rem; }
.maxed-mark {
  display: inline-block;
  padding: 0 6px;
  font-size: .6875rem;
  font-weight: 700;
  line-height: 1.5;
  letter-spacing: .06em;
  text-transform: uppercase;
  /* Filled (7O, Alex's walkthrough): a maxed profession is an achievement, and there are few on a card */
  color: var(--bg);
  white-space: nowrap;
  background: var(--warning);
  border: 1px solid var(--warning);
  border-radius: 999px;
}
/* On your own card: a small menu and a toggle, always in the heading row */
select.profession-spec-select,
select.riding-select { width: auto; max-width: 100%; min-height: 28px; padding: 0 26px 0 8px; font-size: .9375rem; }
select.profession-spec-select.is-none,
select.riding-select.is-none { color: var(--text-muted); }
.profession-maxed-toggle {
  min-height: 28px;
  padding: 0 8px;
  font: inherit;
  font-size: .6875rem;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-muted);
  background: none;
  border: 1px dashed var(--border);
  border-radius: 999px;
  cursor: pointer;
}
.profession-maxed-toggle:hover,
.profession-maxed-toggle:focus-visible { color: var(--text); border-color: var(--text-muted); }
/* Pressed: "Max" on the filled chip the read-only mark uses */
.profession-maxed-toggle[aria-pressed="true"] { color: var(--bg); background: var(--warning); border: 1px solid var(--warning); }
.profession-maxed-toggle[aria-pressed="true"]:hover,
.profession-maxed-toggle[aria-pressed="true"]:focus-visible { color: var(--bg); background: color-mix(in srgb, var(--warning), #fff 18%); border-color: var(--text); }
/* Riding (7M): the details row's small menu, and Exalted with's flag */
.riding { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.riding-icon { flex: none; width: 24px; height: 24px; border-radius: 4px; }

.recipe-chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 8px; padding: 0; list-style: none; }
.recipe-chip {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  max-width: 100%;
  padding: 2px 4px 2px 10px;
  font-size: .9375rem;
  background: var(--raised);
  border: 1px solid var(--border);
  border-radius: 999px;
}
.recipes:not(.is-own) .recipe-chip { padding-right: 10px; }
/* "and 11 more" after the first chips, and "Show fewer" once opened (7C.2), in the quiet "+ Add" style */
.recipe-chips-more { display: inline-flex; align-items: center; padding: 0 4px; }
.recipe-chip-name { display: inline-flex; align-items: center; gap: 6px; min-width: 0; min-height: 28px; padding: 0; border: 0; background: none; color: inherit; font: inherit; text-align: left; overflow-wrap: anywhere; cursor: pointer; }
.recipe-chip-name:hover,
.recipe-chip-name:focus-visible,
.recipe-chip-name[aria-expanded="true"] { color: var(--red-text); text-decoration: underline; text-underline-offset: 3px; }
/* The recipe's icon on its chip and in the pick list (7I.3), when one was read from Wowhead; the name always says it in words. */
.recipe-chip-icon { flex: none; width: 18px; height: 18px; border-radius: 3px; }
.recipe-chip:has(.recipe-chip-icon) { padding-left: 4px; }
/* Wowhead's names in the pick list (7K.2): a quiet heading over them, and a muted line while the site asks. */
.recipe-pick-group,
.recipe-pick-wait { padding: 6px 12px 2px; font-size: .8125rem; color: var(--text-muted); cursor: default; }
.recipe-pick-wait { padding-bottom: 6px; font-style: italic; }
/* A small ring turning beside words that say the site is waiting on Wowhead (7K.2); it stands still for those who ask for less motion. */
.spinner { display: inline-block; width: 12px; height: 12px; margin-right: 8px; vertical-align: -1px; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: spin .8s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
.recipe-pick-icon { display: inline-block; width: 18px; height: 18px; margin-right: 8px; border-radius: 3px; vertical-align: -3px; }
/* A recipe's card (7I.3): what the chip pressed, or the recipe just added, is and does, and the way to it on its profession's page. */
.recipe-card { margin: 0 0 10px; padding: 10px 12px; background: var(--raised); border: 1px solid var(--border); border-radius: 6px; }
.recipe-card-head { display: flex; align-items: center; gap: 10px; }
.recipe-card-icon { flex: none; width: 36px; height: 36px; border-radius: 4px; }
.recipe-card-name { font-size: 1rem; overflow-wrap: anywhere; }
.recipe-card-line { margin: 8px 0 0; line-height: 1.45; overflow-wrap: break-word; }
.recipe-card-status { margin: 8px 0 0; font-size: .875rem; color: var(--text-muted); }
.recipe-card-link { display: inline-block; margin-top: 8px; padding: 4px 0; font-size: .9375rem; }
.recipe-remove { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; padding: 0; border: 0; border-radius: 999px; background: none; color: var(--text-muted); font: inherit; font-size: 1.125rem; line-height: 1; cursor: pointer; }
.recipe-remove:hover,
.recipe-remove:focus-visible { background: var(--red-fill); color: var(--text); }
.recipe-none { margin: 0; font-size: .9375rem; }
.recipe-count { margin: 0; font-size: .875rem; white-space: nowrap; }

/* The box and its pick list, which drops down over whatever is below */
.recipe-add { position: relative; display: flex; align-items: center; gap: 10px; }
[hidden].recipe-add, [hidden].add-open { display: none; }

/* With no chips the box waits behind a quiet link, in "Add level"'s style (7C) */
.add-open { padding: 2px 0; border: 0; background: none; color: var(--text-muted); font: inherit; font-size: .9375rem; text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.add-open:hover,
.add-open:focus-visible { color: var(--red-text); }
.milestones > .add-open,
.milestones > .recipe-add { margin-bottom: 12px; }

input[type=text].input-recipe { flex: 1 1 auto; min-width: 0; min-height: 36px; padding: 4px 10px; font-size: .9375rem; }
.recipe-picks {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 5;
  margin: 2px 0 0;
  padding: 4px 0;
  list-style: none;
  background: var(--raised);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 8px 24px rgba(0, 0, 0, .5);
  max-height: 18rem;   /* an empty box lists every name on the profession (7F): it scrolls */
  overflow-y: auto;
  overscroll-behavior: contain;
}
.recipe-pick { padding: 6px 12px; cursor: pointer; overflow-wrap: anywhere; }
.recipe-pick.is-highlighted,
.recipe-pick:hover { background: var(--red-fill); }
.recipe-pick.is-new { color: var(--red-text); border-top: 1px solid var(--border); }
.recipe-pick.is-new.is-highlighted,
.recipe-pick.is-new:hover { color: var(--text); }
.recipe-pick.is-note { color: var(--text-muted); font-size: .875rem; cursor: default; }
.recipe-pick.is-note:hover { background: none; }
[hidden].recipe-picks { display: none; }

/* The roster line: a profession's icon as a link keeps its size and gains a red edge on hover */
a.roster-glyph { border-radius: 4px; }
a.roster-glyph:hover .game-icon,
a.roster-glyph:focus-visible .game-icon { border-color: var(--red-text); box-shadow: 0 0 0 1px var(--red-text); }

/* The profession's page */
.profession-strip { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 16px; }
.profession-strip-item { display: inline-flex; padding: 3px; border: 1px solid transparent; border-radius: 6px; }
.profession-strip-item:hover,
.profession-strip-item:focus-visible { border-color: var(--border); background: var(--surface); }
.profession-strip-item.is-current { border-color: var(--red-text); background: var(--surface); }
.profession-strip-icon { width: 36px; height: 36px; }
.profession-strip-name { padding: 6px; font-size: .875rem; }
.profession-heading h1 { display: flex; align-items: center; gap: 12px; }
.profession-title-icon { width: 48px; height: 48px; }
.profession-counts { margin: 0; }

.recipe-filter { display: flex; align-items: center; gap: 12px; margin: 0 0 12px; }
input[type=search].input-find { flex: 0 1 360px; min-width: 0; }
.recipe-elsewhere { margin: -4px 0 12px; color: var(--text-muted); }
[hidden].recipe-elsewhere, [hidden].recipe { display: none; }

.recipe-list { display: grid; gap: 10px; margin: 0 0 16px; padding: 0; list-style: none; }
@media (min-width: 760px) {
  .recipe-list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.recipe { display: flex; flex-direction: column; gap: 6px; margin: 0; padding: 10px 14px; }
.recipe-title { margin: 0; font-size: 1.25rem; overflow-wrap: anywhere; }
/* Wowhead (7G): the small link after a recipe's name, in words with our own arrow; its padding makes a finger-sized target without taking the row's room. */
.wowhead-link { display: inline-flex; align-items: center; gap: 4px; flex: none; margin: -6px -4px; padding: 6px 4px; font-size: .875rem; color: var(--text-muted); text-decoration: underline; text-decoration-color: var(--border); text-underline-offset: 3px; white-space: nowrap; }
.wowhead-link:hover,
.wowhead-link:focus-visible { color: var(--red-text); text-decoration-color: currentColor; }
.wowhead-link .icon { width: 14px; height: 14px; }
.recipe-wowhead { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; min-width: 0; }
.recipe-wowhead-label { font-size: .875rem; color: var(--text-muted); }
input[type=text].input-wowhead { flex: none; width: 10ch; }
.recipe-wowhead .level-status { flex-basis: 100%; }
/* The GM's "What it does" box (7I): a row of its own under the name and Spell boxes, the icon read from Wowhead beside it. */
.recipe-effect-box { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; flex: 1 1 100%; min-width: 0; }
.recipe-effect-box-icon { flex: none; align-self: flex-start; width: 28px; height: 28px; border-radius: 3px; }
textarea.input-effect { flex: 1 1 240px; min-width: 0; max-width: 640px; resize: vertical; }
.recipe-effect-box .level-confirm { align-self: flex-start; }
.recipe-effect-note { flex-basis: 100%; font-size: .875rem; color: var(--text-muted); }
/* How the spell id came (7I.2), in words; one the GM still has to set gets a warning mark too, so it isn't color alone. */
.recipe-match-note { flex-basis: 100%; font-size: .875rem; color: var(--text-muted); }
.recipe-match-note.is-unmatched,
.recipe-match-note.is-renamed { color: var(--warning); }
.recipe-match-note.is-renamed strong { color: var(--text); font-weight: 600; }
.recipe-match-note .add-open { font-size: .875rem; }
.recipe-match-note .icon { width: 14px; height: 14px; vertical-align: -2px; }
.recipe-effect-note .add-open { font-size: .875rem; }
.recipe-effect-box .level-status { flex-basis: 100%; }
.recipe-effect-box .level-status:empty { display: none; }
.recipe-people { display: flex; flex-wrap: wrap; gap: 4px 18px; margin: 0; padding: 0; list-style: none; }
.recipe-person { display: inline-flex; align-items: center; gap: 6px; min-width: 0; padding: 2px 6px 2px 2px; border-radius: 4px; }
.recipe-person.is-you { box-shadow: inset 3px 0 0 var(--red-text); padding-left: 8px; }
.recipe-person-kind { display: inline-flex; flex: none; gap: 3px; }
.recipe-person-icon { width: 26px; height: 26px; border-radius: 3px; }
.recipe-person-name { font-size: 1rem; overflow-wrap: break-word; }
.recipe-person .main-star .icon { width: 15px; height: 15px; }
.recipe-holders { margin-bottom: 20px; }
.recipes-heading { margin: 0 0 10px; scroll-margin-top: 12px; }

/* The admin's edit view (5H, second session): a name box, Merge into…, Hide, and Delete on each row; the hidden recipes at the end. */
.recipe-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; }
.recipe-rename { display: flex; align-items: center; gap: 8px; flex: 1 1 320px; min-width: 0; }
.input-recipe-name { flex: 1 1 auto; min-width: 0; max-width: 420px; font-size: 1.125rem; }
.recipe-merge,
.recipe-hide,
.recipe-show,
.recipe-delete { display: flex; align-items: center; gap: 8px; margin: 0; }
.recipe-merge select { max-width: 260px; }
.recipe-nobody { margin: 0; font-size: .9375rem; }
.recipe-hidden { margin-bottom: 16px; }
.recipe-hidden > p { margin: 0 0 10px; }
.recipe-hidden-list { display: grid; gap: 10px; margin: 0; padding: 0; list-style: none; }
.recipe.is-hidden { border-style: dashed; opacity: .85; }
.recipe.is-hidden .recipe-title { font-size: 1.125rem; color: var(--text-muted); }

/* Newly learned (5H.2): the professions index's board and the roster's tile (the home panel became Guild News in 7D). */
.recent-recipes { display: grid; gap: 6px; margin: 0; padding: 0; list-style: none; }
.recent-recipe { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; min-width: 0; padding: 2px 6px 2px 2px; border-radius: 4px; }
.recent-recipe.is-you { box-shadow: inset 3px 0 0 var(--red-text); padding-left: 8px; }
.recent-recipe-profession { display: inline-flex; flex: none; }
.recent-recipe-icon { width: 24px; height: 24px; border-radius: 4px; }
.recent-recipe-by { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
.recent-recipe-age { margin-left: auto; font-size: .875rem; white-space: nowrap; cursor: default; }
@media (max-width: 559px) {
  .recent-recipe {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas:
      "icon name age"
      ".    by   by";
    gap: 2px 10px;
  }
  .recent-recipe-profession { grid-area: icon; }
  .recent-recipe-name { grid-area: name; }
  .recent-recipe-age { grid-area: age; margin-left: 0; }
  .recent-recipe-by { grid-area: by; }
  .recent-recipe-card { grid-column: 2 / -1; }
}
/* Guild News (7D): the home panel collapsed to the newest line, and the Guild News page. */
.news-lines { display: grid; gap: 6px; margin: 0; padding: 0; list-style: none; }
/* Icon, words, age, and (the Guild Master's posts) Edit and Remove, which take a row of their own on a phone. */
/* Since 7P the reactions sit between the words and the age; since 7Q the age's column is one width on every line ("10m", "2d", "Sep 30"), so the reactions end at the same place whatever the age says. */
/* The Guild Master's tools on a post sit before the reactions, so the age stays in its column on those lines too. */
.news-line { position: relative; display: grid; grid-template-columns: 56px minmax(0, 1fr) auto auto 46px; grid-auto-flow: row dense; align-items: start; gap: 4px 10px; min-width: 0; padding: 2px 6px 2px 2px; border-radius: 4px; }
.news-line > .news-tools, .news-line > .news-pin-tools { grid-column: 3; }
.news-line > .news-reacts { grid-column: 4; justify-self: end; }
.news-line > .news-age { grid-column: 5; }
.news-line.is-you { box-shadow: inset 3px 0 0 var(--red-text); padding-left: 8px; }
.news-icon { display: inline-flex; flex: none; align-items: center; justify-content: center; width: 28px; height: 28px; }
.news-game-icon { width: 24px; height: 24px; border-radius: 4px; }
.news-mark { color: var(--text-muted); }
.news-mark .icon { width: 22px; height: 22px; }
.news-emblem { width: 26px; height: 26px; color: var(--text-muted); }
/* A character's day (7M): each part's icon (Alex's, in assets/icons/marks) and each profession's */
.news-mark-icon { display: inline-flex; }
.news-prof-icon { display: inline-flex; }
.news-profession { color: inherit; font-weight: 600; text-decoration: underline; text-decoration-color: var(--border); text-underline-offset: 3px; }
.news-profession:hover,
.news-profession:focus-visible { color: var(--red-text); text-decoration-color: currentColor; }
.news-mark-post .news-emblem { color: var(--red-text); }
/* The column, 56px on every line: the emblem on welcomes, anniversaries, and posts, and on a character's day its first part's icon (7Q; empty since 7P). */
.news-line .news-icon { width: 56px; height: auto; min-height: 28px; justify-content: flex-start; padding-left: 6px; }
.news-lead-icon > * { display: inline-flex; }
/* A day's other parts: each one's small icon just before its words (7P). A long name wraps between its two parts. */
.news-inline-icons { display: inline-flex; gap: 3px; margin-right: 5px; vertical-align: -5px; }
.news-inline-icons > * { display: inline-flex; }
.news-inline-icons .news-game-icon { width: 20px; height: 20px; }
.news-text { min-width: 0; line-height: 28px; overflow-wrap: break-word; }
.news-person .main-star { display: inline-flex; margin-left: 4px; vertical-align: -3px; }
.news-nowrap { white-space: nowrap; }
.news-recipe { font-weight: 700; }
/* A recipe's name opens its card under the line (7K.3), as a chip's does on My characters. */
.news-recipe-name,
.recent-recipe-name { padding: 0; border: 0; background: none; color: inherit; font: inherit; font-weight: 700; text-align: left; overflow-wrap: anywhere; cursor: pointer; }
.news-recipe-name:hover,
.news-recipe-name:focus-visible,
.news-recipe-name[aria-expanded="true"],
.recent-recipe-name:hover,
.recent-recipe-name:focus-visible,
.recent-recipe-name[aria-expanded="true"] { color: var(--red-text); text-decoration: underline; text-underline-offset: 3px; }
.news-recipe-card { grid-column: 2 / -1; margin: 2px 0 6px; font-weight: 400; line-height: normal; }
.recent-recipe-card { flex: 1 0 100%; margin: 4px 0 6px; }
.news-post-body { font-weight: 600; }
/*
 * A post's item (7N): under the words, the icon, the name in its quality's
 * color, and the quality in small capitals (the word is always there, so the
 * color never carries it alone), a button opening its card under the line.
 * Wowhead's quality colors, rare and epic lightened to 4.5:1 on --raised
 * (the prototype's contrast math, as class colors are).
 */
.item-quality-0 { color: #9D9D9D; }
.item-quality-1 { color: var(--text); }
.item-quality-2 { color: #1EFF00; }
.item-quality-3 { color: #2F8DFC; }
.item-quality-4 { color: #C25BFF; }
.item-quality-5 { color: #FF8000; }
.item-quality-6 { color: #E6CC80; }
.item-quality-7 { color: #00CCFF; }
.item-quality-word { font-size: .75rem; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--text-muted); white-space: nowrap; }
.news-item { display: block; line-height: normal; margin: 4px 0 2px; }
.news-item-name { display: inline-flex; align-items: center; gap: 8px; max-width: 100%; padding: 3px 8px 3px 3px; font: inherit; text-align: left; color: inherit; background: none; border: 1px solid var(--border); border-radius: 6px; cursor: pointer; }
.news-item-name:hover, .news-item-name[aria-expanded="true"] { background: var(--raised); border-color: var(--text-muted); }
.news-pinned .news-item-name:hover, .news-pinned .news-item-name[aria-expanded="true"] { background: var(--surface); }
.news-item-icon { flex: none; width: 28px; height: 28px; border-radius: 4px; }
.news-item-words { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; min-width: 0; }
.news-item-title { font-weight: 600; overflow-wrap: break-word; min-width: 0; }
.news-pinned .news-item-card { background: var(--surface); }
.item-card-title { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; min-width: 0; }
.item-card-line { margin: 6px 0 0; line-height: 1.45; overflow-wrap: break-word; }
.recipe-card-head + .item-card-line { margin-top: 8px; }
.item-card-link { margin: 8px 0 0; }
.news-post-item { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.news-post-item label { font-size: .9375rem; }
.news-post-item .item-box { width: 28em; max-width: 100%; }
.news-more { padding: 0; border: 0; background: none; color: var(--text-muted); font: inherit; text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.news-more:hover { color: var(--text); }
.news-age { font-size: .875rem; line-height: 28px; text-align: right; white-space: nowrap; cursor: default; }
/*
 * Reactions (7P): only the ones someone gave, each a small pill, the icon a
 * button and the count beside it (the names on hover and a tap). Yours has
 * the red outline and a filled icon, so it never rests on color alone. The
 * picker, all three in a small raised bar over the line's end, shows on
 * hover and focus, and with a tap on the line by touch (.is-reacting,
 * news.js); Alex's choice of three looks (7P).
 */
.news-reacts { display: inline-flex; align-items: center; gap: 4px; min-height: 28px; }
.news-reacts.is-empty { gap: 0; }
.news-react-pills { display: inline-flex; align-items: center; gap: 4px; }
.news-react { display: inline-flex; align-items: center; gap: 1px; height: 24px; padding: 0 7px 0 2px; border: 1px solid var(--border); border-radius: 12px; color: var(--text-muted); font-size: .8125rem; line-height: 1; white-space: nowrap; }
.news-react.is-mine { border-color: var(--red-text); color: var(--text); background: rgba(142, 27, 27, .28); }
.news-react-button { display: inline-flex; align-items: center; justify-content: center; padding: 2px; border: 0; border-radius: 10px; background: none; color: inherit; cursor: pointer; }
.news-react-mark { display: inline-flex; padding: 2px; }
.news-react-icon { width: 16px; height: 16px; fill: none; }
.news-react.is-mine .news-react-icon,
.news-react-button.is-mine .news-react-icon { fill: currentColor; fill-opacity: .35; color: var(--red-text); }
.news-react-button:hover,
.news-react-button:focus-visible { color: var(--text); background: var(--border); }
.news-react-count { padding: 2px 0; cursor: help; }
.news-react-picker { position: absolute; z-index: 2; top: 1px; right: 4px; display: flex; gap: 2px; padding: 2px 4px; border: 1px solid var(--border); border-radius: 14px; background: var(--raised); box-shadow: 0 2px 8px rgba(0, 0, 0, .45); opacity: 0; pointer-events: none; transition: opacity .12s; }
.news-lines-board .news-react-picker { top: 5px; }
.news-react-picker .news-react-button { padding: 3px; color: var(--text-muted); }
.news-react-picker .news-react-button.is-mine { color: var(--text); box-shadow: inset 0 0 0 1px var(--red-text); }
.news-react-picker .news-react-icon { width: 18px; height: 18px; }
.news-line.is-reacting .news-react-picker,
.news-react-picker:focus-within { opacity: 1; pointer-events: auto; }
@media (hover: hover) {
  .news-line:hover .news-react-picker { opacity: 1; pointer-events: auto; }
}
/* The collapsed home line shows only what it has: a press there adds or takes back yours, a new one waits for the open list. */
[data-news-summary] .news-react-picker { display: none; }
.news-react-error { grid-column: 2 / -1; margin: 0; font-size: .875rem; }
@media (max-width: 559px) {
  /* On a phone the icon's column and the age's take only what they need, so the words get the room */
  .news-line { grid-template-columns: 34px minmax(0, 1fr) auto auto minmax(26px, auto); gap: 4px 8px; }
  .news-line .news-icon { width: 34px; padding-left: 2px; }
  .news-line > .news-reacts:not(.is-empty) { grid-column: 2 / -1; grid-row: 2; justify-self: start; }
  .news-react { height: 30px; padding-right: 9px; }
  .news-react-button { padding: 5px; }
  .news-react-picker .news-react-button { padding: 7px; }
}
.news-tools { display: inline-flex; gap: 6px; }
@media (max-width: 559px) {
  .news-line > .news-tools { grid-column: 2 / -1; }
}
.news-tools form { margin: 0; }
.home-news .heat-heading { align-items: center; }
.home-news.is-collapsed .heat-heading { margin-bottom: 0; }
/* The newest line on a row of its own under the heading (7Q.2), lined up with the open list; under a pinned post it sits in by the band's padding */
.news-summary-below { margin-top: 10px; cursor: pointer; }
.news-pinned + .news-summary-below { margin-top: 8px; padding: 0 8px; }
.home-news:not(.is-collapsed) [data-news-summary] { display: none; }
.home-news-empty { margin: 0; }
/* The GM's pinned post (7L): a tinted band under the heading row, open or not, with the newest news line under it rather than beside the heading, so the post leads and never pushes the news off. */
.news-pinned { margin-top: 10px; padding: 6px 8px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--raised); }
.home-news:not(.is-collapsed) .news-pinned { margin: 0 0 12px; }
.home-news:not(.is-collapsed) .news-summary-below { display: none; }
.news-pin-tools { display: inline-flex; align-items: center; gap: 10px; }
.news-pin-tools form { margin: 0; }
.news-unpin { padding: 0; border: 0; background: none; color: var(--text-muted); font: inherit; font-size: .875rem; line-height: 28px; text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.news-unpin:hover,
.news-unpin:focus-visible { color: var(--text); }
.news-pin-remove { min-height: 28px; padding: 0 9px; }
.news-pin-remove > span[aria-hidden] { font-size: 1.125rem; line-height: 1; }
@media (max-width: 559px) {
  .news-line > .news-pin-tools { grid-column: 2 / -1; }
}
.news-post-panel { margin-bottom: 16px; }
.news-post-panel .hint { margin-bottom: 0; }
/* One column that may shrink, so the Item box never pushes the form past a phone's edge (7Q) */
.news-post-form { display: grid; grid-template-columns: minmax(0, 1fr); gap: 6px; margin: 0; }
.news-post-row { display: flex; gap: 8px; align-items: center; }
.news-post-row input { flex: 1 1 auto; min-width: 0; }
.news-post-row .btn { flex: none; }
.news-line.is-editing { display: block; padding: 8px 4px; }
.news-filter { margin: 0; }
.news-filter select { width: auto; }
.news-count { margin: 0; margin-left: auto; }
.news-lines-board { gap: 0; }
.news-lines-board .news-line { padding: 8px 8px 8px 4px; border-bottom: 1px solid var(--border); border-radius: 0; }
.news-lines-board .news-line.is-you { padding-left: 10px; }
.news-lines-board .news-line:last-child { border-bottom: 0; }
.news-none { margin: 0; }
.news-older { margin-top: 12px; }
.news-share { margin-top: 16px; }
.news-share .hint { margin-bottom: 0; }
/* The professions index: every profession's icon in a box like the home page's role boxes, the recipe count under it. */
.profession-summary { justify-content: center; margin: 0 0 20px; }
/* One row of every profession on a monitor; four to a row on a phone and six
   in between, rather than a row that runs off the page. */
.profession-summary ul { grid-auto-flow: row; grid-template-columns: repeat(4, minmax(0, 1fr)); width: 100%; }
@media (min-width: 560px) {
  .profession-summary ul { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}
@media (min-width: 960px) {
  .profession-summary ul { grid-template-columns: repeat(auto-fill, minmax(64px, 1fr)); }
}
.profession-summary a { grid-template-columns: auto; justify-items: center; gap: 4px; padding: 8px 10px 6px; }
.profession-summary .game-icon { width: 40px; height: 40px; }
.profession-summary-count { min-height: 1em; font-size: 1.125rem; line-height: 1; color: var(--text-muted); }
.profession-summary-name { font-size: .75rem; }
.recent-board { margin-top: 16px; }
.recent-filter { margin: 0; }
.recent-filter select { width: auto; }
.recent-count { margin: 0; margin-left: auto; }
.recent-recipes-board { gap: 8px; }
.recent-recipes-board .recent-recipe { padding: 6px 8px 6px 4px; border-bottom: 1px solid var(--border); border-radius: 0; }
.recent-recipes-board .recent-recipe:last-child { border-bottom: 0; }
.recent-none { margin: 0; }
.recent-older { margin-top: 12px; }
.recipe-new { margin-left: 8px; vertical-align: middle; color: var(--red-text); border-color: var(--red-text); }
.profession-tile {
  display: grid;
  justify-items: center;
  align-content: center;
  gap: 2px;
  padding: 6px 14px 4px;
  color: var(--text);
  text-decoration: none;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.profession-tile:hover { border-color: var(--text-muted); }
.profession-tile-fan { display: flex; height: 36px; align-items: center; }
.profession-tile-icon, .offer-tile-icon { width: 30px; height: 30px; border-radius: 4px; border: 1px solid var(--bg); }
.profession-tile-icon + .profession-tile-icon { margin-left: -10px; }
.profession-tile .role-summary-flex { grid-column: auto; }
.recipe-holders > p { margin: 0; }
.recipe-people-wide { gap: 6px 20px; }
/* The people box grouped by specialization (7M) */
.recipe-holder-group { margin: 14px 0 6px; font-family: var(--font-body); font-size: .8125rem; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--text-muted); }
.recipe-holders h2 + .recipe-holder-group { margin-top: 0; }
.recipe-list-empty { margin: 0 0 16px; }

/* The recipe list (7H): a row per recipe, its name a button revealing who knows it; the characters above filter it. */
.recipe-holder-button { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 0 6px; min-height: 32px; margin: -2px -6px; padding: 2px 6px; font: inherit; color: var(--text); text-align: left; background: none; border: 1px solid transparent; border-radius: 4px; cursor: pointer; }
.recipe-holder-button:hover { border-color: var(--border); }
.recipe-holder-button[aria-pressed="true"] { background: var(--raised); border-color: var(--red-text); }
.recipe-holder-button .main-star .icon { width: 15px; height: 15px; }
/* With no recipes on the page, nothing to filter: the name is plain (the review's session 3) */
.recipe-holder-plain { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 0 6px; min-height: 32px; }
.recipe-holder-plain .main-star .icon { width: 15px; height: 15px; }
.recipe-holder-count { color: var(--text-muted); }
.recipe-who-line { margin: -4px 0 12px; }
.recipe-browse { display: grid; gap: 16px; margin: 0 0 16px; }
.recipe-rows { margin: 0; padding: 0; list-style: none; }
.recipe-rows.is-empty,
.recipe-rows.is-empty + .recipe-side { display: none; }
.recipe-row { padding: 0 12px; }
.recipe-row:not([hidden]) ~ .recipe-row:not([hidden]) { border-top: 1px solid var(--border); }
.recipe-row.is-you { box-shadow: inset 3px 0 0 var(--red-text); }
.recipe-row.is-open { background: var(--raised); }
[hidden].recipe-row { display: none; }
.recipe-row-head { display: flex; flex-wrap: wrap; align-items: center; gap: 0 12px; min-width: 0; cursor: pointer; }
.recipe-row-title { flex: 0 1 auto; min-width: 0; margin: 0; font-size: 1.125rem; }
.recipe-row-toggle { display: inline-flex; align-items: baseline; gap: 8px; min-height: var(--tap); padding: 10px 0; font: inherit; color: var(--text); text-align: left; background: none; border: 0; cursor: pointer; }
.recipe-row-name { overflow-wrap: anywhere; }
.recipe-row-count { flex: none; font-family: var(--font-body); font-size: .9375rem; font-weight: 400; color: var(--text-muted); }
.recipe-row-arrow { flex: none; width: 14px; height: 14px; color: var(--text-muted); transform: rotate(-90deg); transition: transform .15s; align-self: center; }
.recipe-row.is-open .recipe-row-arrow { transform: none; }
.recipe-row-head .recipe-new { margin-left: 0; }
.recipe-row-head .wowhead-link { margin-left: auto; margin-right: 0; }
.recipe-row-who { padding: 0 0 12px 22px; cursor: auto; }
.recipe-side { position: sticky; top: 12px; max-height: calc(100vh - 24px); overflow-y: auto; overscroll-behavior: contain; padding: 14px 16px; }
.recipe-side-empty { margin: 0; }
.recipe-side-title { margin: 0; font-size: 1.5rem; overflow-wrap: anywhere; }
.recipe-side-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; margin: 4px 0 0; }
.recipe-side-meta .recipe-new { margin-left: 0; }
.recipe-side-meta .wowhead-link { margin: -6px -4px; }
.recipe-side-count { margin: 6px 0 12px; color: var(--text-muted); }
.recipe-side .recipe-people { flex-direction: column; gap: 6px; }
/* What it does (7I): the recipe's icon and one line, above the people, in the panel and in a row opened in place. Plain text, never Wowhead's colors. */
.recipe-effect { display: flex; align-items: flex-start; gap: 10px; margin: 0 0 10px; }
.recipe-effect-icon { flex: none; width: 36px; height: 36px; border-radius: 4px; }
.recipe-effect-line { margin: 0; line-height: 1.45; overflow-wrap: break-word; }
.recipe-side .recipe-effect { margin: 12px 0 0; }
/* On a monitor who knows it shows in the panel beside the list; on a narrower screen, under the row. */
@media (min-width: 760px) {
  .recipe-browse { grid-template-columns: minmax(0, 11fr) minmax(0, 9fr); align-items: start; }
  .recipe-browse .recipe-row-who { display: none; }
}
@media (max-width: 759px) {
  .recipe-side { display: none; }
}
/* On a phone every row has one shape: the name (and how many know it) on its own line, the New tag and the Wowhead link under it. */
@media (max-width: 559px) {
  .recipe-row-head { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: 0 8px; padding-bottom: 6px; }
  .recipe-row-title { grid-column: 1 / -1; }
  .recipe-row-toggle { min-height: 38px; padding-bottom: 0; }
  .recipe-row-head .recipe-new { grid-column: 1; margin-left: 22px; }
  .recipe-row-head .wowhead-link { grid-column: 2; justify-self: end; margin: -6px -4px; }
}
.recipe-filter .num { white-space: nowrap; }
.recipe-own-hint { margin: 0; font-size: .9375rem; }


/* --------------------------------------------------------------------------
   Attunements and keys (5G): an "Attunements and keys" section on each My
   characters card (the recipe chips' look, with a pick list of the admin's),
   the key on an event's heading, line, and signups (a held place before the
   "can also" column), the fifth roster filter, and the editors' extra
   controls.
   -------------------------------------------------------------------------- */
.milestones-heading .icon { width: 20px; height: 20px; margin-right: 8px; vertical-align: -4px; color: var(--text-muted); }
.milestones-heading .game-icon { border-radius: 4px; }
.recipe-chip.is-hidden { color: var(--text-muted); border-style: dashed; }
/* The held place for the key on a signup's line: before the "can also" slot, which then sits beside it */
.signup-person .milestone-slot { margin-left: auto; align-items: center; justify-content: center; }
.signup-person .milestone-slot + .role-slot { margin-left: 0; }
.signup-maybe + .milestone-slot { margin-left: 0; }
.milestone-slot .icon { width: 20px; height: 20px; color: var(--text); }
.event-needs { display: inline-flex; align-items: center; gap: 6px; }
.event-needs .icon { width: 18px; height: 18px; }
/* "6 of 8 are attuned" under the count of people on an event's line (5K) */
.event-attuned { display: inline-flex; align-items: center; gap: 5px; }
.event-attuned .icon { width: 15px; height: 15px; color: var(--text); }
.signups-attuned { display: inline-flex; align-items: center; gap: 6px; }
.signups-attuned .icon { width: 18px; height: 18px; }
.signup-attune-hint .icon { color: var(--text-muted); }
@media (min-width: 760px) {
  .roster-filters.has-milestones { grid-template-columns: repeat(5, minmax(0, 1fr)); }
}
/* The editors: a raid's size and what an instance needs, on the row */
.dungeon-item select.size-menu { flex: none; width: auto; }
.dungeon-item select.needs-menu { flex: 0 1 260px; min-width: 180px; width: auto; }
.dungeon-size { display: flex; align-items: center; gap: 8px; white-space: nowrap; }
.milestone-ticks { font-size: .875rem; white-space: nowrap; }


/* --------------------------------------------------------------------------
   Marks you can read by touch (7E): a press on a [data-tip] mark shows its
   hover words in a small bubble (assets/js/tips.js), above the mark or below
   it when there's no room, always inside the screen. It sits over the page,
   so the line under it never moves. A help cursor on a monitor says a press
   will explain; links keep the pointer.
   -------------------------------------------------------------------------- */

[data-tip]:not(a) { cursor: help; -webkit-tap-highlight-color: transparent; }
.tip-bubble {
  position: absolute;
  z-index: 30;
  max-width: min(260px, calc(100vw - 16px));
  padding: 4px 9px;
  background: var(--raised);
  border: 1px solid var(--text-muted);
  border-radius: var(--radius);
  color: var(--text);
  font: 400 .875rem/1.4 var(--font-body);
  overflow-wrap: anywhere;
  pointer-events: auto;
}
.tip-bubble[hidden] { display: none; }
.tip-bubble a { color: var(--red-text); }


/* --------------------------------------------------------------------------
   The guide (7J)
   -------------------------------------------------------------------------- */

/* A member page's footer: the way into the guide */
.site-footer-member { margin-top: 40px; }
.site-footer-member a { color: var(--text-muted); }
.site-footer-member a:hover,
.site-footer-member a:focus-visible,
.site-footer-member a[aria-current] { color: var(--text); }

/* The link after a page's heading: a question mark in a circle, quiet until
   reached for. Its padding makes a finger-sized target without taking room. */
.guide-help { display: inline-flex; margin: -8px; padding: 8px; color: var(--text-muted); line-height: 1; border-radius: var(--radius); }
.guide-help .icon { width: 20px; height: 20px; }
.guide-help:hover,
.guide-help:focus-visible { color: var(--red-text); }
/* In a heading row the heading gives up its push to the link after it */
.page-heading h1:has(+ .guide-help) { margin-right: 0; }
.page-heading h1 + .guide-help { margin-right: auto; }
.page-heading.is-plain { margin-bottom: 0; }

.guide-intro { max-width: 70ch; margin: 0 0 20px; }
.guide { display: grid; gap: 20px; align-items: start; }
.guide-contents { padding: 12px 16px; }
.guide-contents ol { display: grid; gap: 2px; margin: 0; padding: 0; list-style: none; }
.guide-contents a { display: block; padding: 5px 0; color: var(--text-muted); text-decoration: none; }
.guide-contents a:hover,
.guide-contents a:focus-visible { color: var(--text); text-decoration: underline; text-underline-offset: 3px; }
.guide-sections { min-width: 0; }
.guide-section { max-width: 72ch; padding: 0 0 24px; margin: 0 0 24px; border-bottom: 1px solid var(--border); scroll-margin-top: 16px; }
.guide-section:last-child { border-bottom: 0; }
.guide-section h2 { margin: 0 0 10px; }
/* A section's words sit in from its heading, so the eye tells the two apart */
.guide-body { padding-left: 24px; }
@media (max-width: 559px) {
  .guide-body { padding-left: 14px; }
}
.guide-section:target h2 { color: var(--red-text); }
/* A section's own words: short paragraphs, steps, and "Good to know" */
.guide-section h3 { margin: 18px 0 6px; font-family: var(--font-body); font-size: .8125rem; font-weight: 700; letter-spacing: .06em; color: var(--text-muted); text-transform: uppercase; }
.guide-section p { margin: 0 0 10px; }
.guide-section ol,
.guide-section ul { margin: 0 0 10px; padding-left: 22px; }
.guide-section li { margin: 0 0 6px; }
.guide-section li::marker { color: var(--text-muted); }
.guide-body > :last-child { margin-bottom: 0; }
.guide-ui { font-weight: 700; }
.guide-said { font-style: normal; }
.guide-section code { padding: 1px 5px; font-size: .9375rem; background: var(--raised); border-radius: 4px; }
/* A named part and what it is: the home page's panels, a rank, a tool */
.guide-parts { display: grid; gap: 8px; margin: 0 0 10px; }
.guide-parts dt { font-weight: 700; }
.guide-parts dd { margin: -6px 0 0; }
/* The legend: each mark as the site draws it, then its words. Every other row
   is shaded, so an icon of an odd size is read with its own words. */
.guide-symbols { display: grid; grid-template-columns: 148px minmax(0, 1fr); margin: 0 0 10px; }
.guide-symbols dt,
.guide-symbols dd { margin: 0; padding: 8px 12px; }
.guide-symbols dt { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; border-radius: var(--radius) 0 0 var(--radius); }
.guide-symbols dd { align-content: center; border-radius: 0 var(--radius) var(--radius) 0; }
.guide-symbols dt:nth-of-type(odd),
.guide-symbols dd:nth-of-type(odd) { background: var(--surface); }
@media (max-width: 559px) {
  .guide-symbols { grid-template-columns: 116px minmax(0, 1fr); }
  .guide-symbols dt,
  .guide-symbols dd { padding: 8px; }
}
.guide-icon { width: 32px; height: 32px; }
.guide-icon-small { width: 22px; height: 22px; }
.guide-mark { display: inline-flex; color: var(--text-muted); }
.guide-mark .icon { width: 22px; height: 22px; }
.guide-mark.is-red { color: var(--red-text); }
.guide-mark.is-warning { color: var(--warning); }
.guide-mark.is-success { color: var(--success); }
.guide-dash { display: inline-block; width: 30px; text-align: center; color: var(--text-muted); }
.guide-yours { display: inline-block; width: 30px; height: 24px; background: var(--surface); border: 1px solid var(--border); border-radius: 4px; box-shadow: inset 4px 0 0 var(--red-text); }
@media (min-width: 960px) {
  .guide { grid-template-columns: 260px minmax(0, 1fr); gap: 32px; }
  .guide-contents { position: sticky; top: 12px; max-height: calc(100vh - 24px); overflow-y: auto; }
}

/* Discord's posts and answers as the guide shows them: plain, in the site's
   own type, in a plain inset. Never an imitation of Discord. */
.guide-discord { max-width: 560px; margin: 8px 0 12px; padding: 10px 14px; overflow-wrap: anywhere; background: var(--surface); border-left: 3px solid var(--border); border-radius: 4px; }
.guide-section .guide-discord p { margin: 0; }
.guide-discord .guide-discord-gap { height: 10px; }
.guide-discord-head { margin-top: 2px; font-weight: 700; }
.guide-discord p + .guide-discord-head { margin-top: 10px; }
.guide-discord-small { font-size: .875rem; color: var(--text-muted); }
.guide-discord-quote { padding-left: 10px; border-left: 3px solid var(--border); }
.guide-discord-link { color: var(--text-muted); text-decoration: underline; text-underline-offset: 3px; }
.guide-section .guide-discord .guide-discord-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.guide-discord-button { padding: 4px 14px; font-size: .9375rem; font-weight: 700; border: 1px solid var(--text-muted); border-radius: 4px; cursor: default; }
.guide-discord-button.is-success { border-color: var(--success); }
.guide-discord-button.is-danger { border-color: var(--danger); }
.guide-commands dd > ul { margin: 6px 0 0; }
/* The GM's line on a part that's switched off */
.guide-off { display: flex; align-items: flex-start; gap: 8px; max-width: 560px; padding: 8px 12px; color: var(--text-muted); border: 1px dashed var(--border); border-radius: var(--radius); }
.guide-off .icon { flex: none; margin-top: 3px; }


/* What a recipe needs (7K.4): under the line in the panel and in a card. A reagent made here opens who makes it, in place. */
.needs { margin: 12px 0 0; }
.needs-list { display: grid; gap: 2px; margin: 0; padding: 0; list-style: none; }
.needs-item { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 8px; min-height: 30px; }
.needs-icon { flex: none; width: 22px; height: 22px; border-radius: 3px; }
.needs-icon-none { display: inline-block; background: var(--raised); border: 1px solid var(--border); }
.needs-name { overflow-wrap: anywhere; }
.needs-toggle { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 2px 8px; margin: -3px -6px; padding: 3px 6px; font: inherit; color: var(--text); text-align: left; background: none; border: 1px solid transparent; border-radius: 4px; cursor: pointer; }
.needs-toggle:hover, .needs-toggle:focus-visible { border-color: var(--border); }
.needs-toggle[aria-expanded="true"] { background: var(--raised); border-color: var(--red-text); }
.needs-count { color: var(--text-muted); font-size: .9375rem; }
.needs-by { display: inline-flex; align-items: center; gap: 4px; color: var(--text-muted); font-size: .875rem; white-space: nowrap; }
.needs-profession-icon { display: inline-block; width: 16px; height: 16px; border-radius: 3px; vertical-align: -3px; }
.needs-wowhead { display: inline-flex; margin: -6px -2px; padding: 6px 4px; color: var(--text-muted); }
.needs-wowhead:hover, .needs-wowhead:focus-visible { color: var(--red-text); }
.needs-wowhead .icon { width: 13px; height: 13px; }
.needs-who { margin: 4px 0 8px 30px; padding: 2px 0 2px 10px; border-left: 2px solid var(--border); }
.needs-who-said { margin: 0 0 6px; font-size: .875rem; color: var(--text-muted); }
.needs-who .recipe-people { flex-direction: column; gap: 4px; }
/* Made by more than one recipe here (the review's session 3): a part per maker */
.needs-who .recipe-people + .needs-who-said { margin-top: 10px; }
.needs-who-said .needs-profession-icon { margin-right: 4px; }
.needs-who-maker { color: var(--text); font-weight: 700; }
.needs-hint { margin: -4px 0 4px 30px; font-size: .875rem; font-style: italic; color: var(--text-muted); }
.needs-extra, .needs-used { margin: 8px 0 0; font-size: .9375rem; color: var(--text-muted); }
.needs-used-name { color: var(--text); text-decoration-color: var(--text-muted); text-underline-offset: 3px; }
.needs-used-name .needs-profession-icon { margin-right: 4px; }
.needs-more { font-size: inherit; }
.needs-card { margin-top: 10px; font-size: .9375rem; }
.needs-card .needs-icon { width: 18px; height: 18px; }
.needs-card .needs-item { min-height: 26px; }
.needs-card .needs-who { margin-left: 26px; }
.recipe-row-knows { margin: 12px 0 6px; }
.recipe-side .recipe-row-knows { display: none; }

/* --------------------------------------------------------------------------
   Items up for grabs (7T), and an item found by name
   -------------------------------------------------------------------------- */
/* An item as a button (_item_button.php): the post's keeps its 7N look; a
   compact one sits in a line, its icon 20px */
.item-chip { display: inline-flex; max-width: 100%; vertical-align: middle; }
.item-chip.is-compact .news-item-name { gap: 6px; padding: 1px 6px 1px 1px; }
.item-chip.is-compact .news-item-icon { width: 20px; height: 20px; border-radius: 3px; }
/* The card beside an item while a mouse rests on it */
.item-hover { position: absolute; z-index: 30; width: max-content; max-width: min(320px, calc(100vw - 16px)); margin: 0; box-shadow: 0 8px 24px rgba(0, 0, 0, .5); pointer-events: none; line-height: normal; }
.item-hover .item-card-link { display: none; }
/* An item with its price, in a line */
.offer-item { display: inline-flex; align-items: center; gap: 6px; max-width: 100%; }
.offer-price { font-size: .875rem; color: var(--text-muted); white-space: nowrap; }
.offer-price.is-free { padding: 0 7px 0 calc(7px + .04em); font-size: .75rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--success); border: 1px solid var(--success); border-radius: 999px; }
.offer-price.is-gold { color: var(--warning); font-weight: 600; }
.offer-items { display: inline-flex; flex-wrap: wrap; gap: 4px 8px; vertical-align: middle; }
/* Each item up for grabs with its price in a box of its own, wherever it shows */
.offer-box { gap: 0; padding-right: 8px; background: var(--surface); border: 1px solid var(--border); border-radius: 6px; }
.offer-box .news-item-name { border: 0; border-radius: 5px 0 0 5px; }
.offers-yours .offer-box, .news-pinned .offer-box { background: var(--bg); }
/* The roster: a faint gold strip after the member's characters, apart from their icon columns */
.roster-offers { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; margin: 10px 0 0; padding: 6px 10px;
  background: color-mix(in srgb, var(--warning), transparent 94%); border: 1px solid color-mix(in srgb, var(--warning), transparent 80%); border-radius: 6px; }
.offer-box .offer-price:not(.is-free) { padding-left: 2px; }
.offer-box .offer-price.is-free { margin-left: 2px; }
.roster-offers .roster-offer-card { margin: 2px 0 0; }
.roster-offers-mark { display: inline-flex; flex: none; }
.roster-offers-icon { width: 20px; height: 20px; border-radius: 3px; }
.roster-offer-card, .home-offer-card { flex-basis: 100%; margin: 4px 0 0; }
/* The home greeting: under the note */
.home-greeting-offers { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 6px 8px; margin-top: 8px; }
.home-greeting-offers-link { display: inline-flex; align-items: center; gap: 6px; color: var(--text-muted); font-size: .9375rem; }
.home-greeting-offers-link:hover { color: var(--text); }
.home-offers-icon { width: 20px; height: 20px; border-radius: 3px; }
/* Each of your items with its × (the review's session 3) */
.home-offer { display: inline-flex; align-items: center; gap: 4px; max-width: 100%; }
.home-offer-remove { display: contents; }
.home-offer .note-remove { margin-left: 0; }
.home-offer-card { text-align: left; }
/* The page */
.offers-intro { margin: -4px 0 18px; color: var(--text-muted); }
.offers-yours h2, .offers-guild h2 { margin: 0 0 10px; font-size: 1.375rem; }
.offers-guild { margin-top: 28px; }
.offers { display: grid; gap: 6px; margin: 0 0 14px; padding: 0; list-style: none; }
.offer-line { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px; padding: 6px 10px; background: var(--surface); border: 1px solid var(--border); border-left-width: 3px; border-radius: 6px; }
.offers-yours .offer-line { background: var(--bg); }
.offer-line.is-you { border-left-color: var(--red-fill); }
.offer-line-item { min-width: 0; }
.offer-from { color: var(--text-muted); }
.offer-days { color: var(--text-muted); font-size: .875rem; white-space: nowrap; }
.offer-tool { margin-left: auto; }
.offer-card { flex-basis: 100%; margin: 2px 0 4px; }
.offers-full { margin: 0; }
.offer-form { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 12px 20px; }
.offer-form-item { flex: 1 1 320px; min-width: 0; }
.offer-form-item label { display: block; margin-bottom: 4px; font-weight: 600; }
.offer-form-item .hint { margin: 4px 0 0; }
.offer-form-price { margin: 0; padding: 0; border: 0; min-width: 0; }
.offer-form-price legend { margin-bottom: 4px; padding: 0; font-weight: 600; }
.offer-prices { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 16px; min-height: 42px; }
.offer-gold { display: inline-flex; align-items: center; gap: 4px; }
input[type=text].input-gold { width: 7em; }
.offer-form > .btn { margin-top: calc(1.5em + 4px); }
/* An item box: the pick list under the box */
.item-box-field { position: relative; }
.item-box input[type=text] { width: 100%; }
.item-picks {
  position: absolute; top: 100%; left: 0; right: 0; z-index: 5;
  margin: 2px 0 0; padding: 4px 0; list-style: none;
  background: var(--raised); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: 0 8px 24px rgba(0, 0, 0, .5);
  max-height: 18rem; overflow-y: auto; overscroll-behavior: contain;
}
[hidden].item-picks { display: none; }
.item-pick { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 10px; padding: 6px 12px; cursor: pointer; }
.item-pick.is-highlighted, .item-pick:hover { background: var(--surface); }
.item-pick-name { font-weight: 600; overflow-wrap: anywhere; }
.item-pick-kind { font-size: .8125rem; color: var(--text-muted); }
.item-box-status { min-height: 1.4em; margin: 2px 0 0; font-size: .875rem; color: var(--text-muted); font-style: italic; }
.item-box-status:empty::before { content: "\00a0"; }
@media (max-width: 559px) {
  .offer-tool { margin-left: 0; }
  .offer-form > .btn { margin-top: 0; }
}
