/* MedEikon Portal - Accordion Component
   ================================================================
   Stylesheet for the merged site > trailer > detail accordion.
   Pairs with medeikon-accordion.js and medeikon-icons.js.

   Load order in the page:
     1. <link rel="stylesheet" href="medeikon-accordion.css">
     2. <script src="medeikon-icons.js"></script>
     3. <script src="medeikon-accordion.js"></script>

   No build step, no external dependencies - plain CSS custom
   properties for theming (light/dark switch toggles a
   [data-theme] attribute on <html>).
   ================================================================ */


/* ---------------------------------------------------------
   Tokens - every colour comes from here
   --------------------------------------------------------- */
:root {
  color-scheme: light;
  --page-bg: #ffffff;
  --panel-bg: #ffffff;
  --stripe: #f4f6f3;
  --ink: #17211d;
  --accent: #538234;
  --accent-hover: #3f6527;
  --on-accent: #ffffff;
  --heading: #3f6527;
  --line: rgba(83, 130, 52, 0.28);
  --rule: rgba(23, 33, 29, 0.12);
  --focus: #538234;
  --ok: #2e7d32;
  --fail: #c62828;
  --radius: 0.65rem;
  --control-height: 2.4rem;

  /* One spacing value for every gap: between tiers, between a tier
     and its contents, and between the panels. Change it here and the
     whole page stays evenly spaced. */
  --gap: 0.75rem;
  --toggle-size: 2.3rem;
  --panel-col: 20rem;
  --indent: clamp(0.6rem, 2.5vw, 2rem);
}

[data-theme="dark"] {
  color-scheme: dark;
  --page-bg: #121711;
  --panel-bg: #1a201a;
  --stripe: #202719;
  --ink: #e6ece3;
  --accent: #4c7a30;
  --accent-hover: #5f9740;
  --on-accent: #ffffff;
  --heading: #9ec97a;
  --line: rgba(158, 201, 122, 0.26);
  --rule: rgba(230, 236, 227, 0.14);
  --focus: #9ec97a;
  --ok: #7fc784;
  --fail: #ef7b7b;
}

* { box-sizing: border-box; }

/* Always reserve room for the scrollbar. Without this, a layout that
   grows the page taller makes the scrollbar appear, which narrows the
   window, which can undo the layout, which removes the scrollbar again -
   the page ends up flickering between two states at certain widths. */
html { scrollbar-gutter: stable; }

body {
  margin: 0;
  background: var(--page-bg);
  color: var(--ink);
  font-family: "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
  transition: background-color 220ms ease, color 220ms ease;
}

button, input, select { font: inherit; }

button:focus-visible,
select:focus-visible,
input:focus-visible + .radio-indicator,
[role="button"]:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
}

svg { display: block; }

/* Stroked icons, drawn in the current text colour */
.icon-glyph {
  width: 100%; height: 100%;
  fill: none; stroke: currentColor;
  stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round;
}

/* MedEikon icons. The green tile has been stripped out of the artwork,
   so these now take their colour from whatever contains them - except
   the signal strengths and feedback faces, which keep their own colours
   because the colour carries the meaning. */
.mei-icon { width: 1.5rem; height: 1.5rem; flex: 0 0 auto; }

/* ---------------------------------------------------------
   Shell
   --------------------------------------------------------- */
.app-shell { display: flex; flex-direction: column; min-height: 100vh; }
.app-body { flex: 1 0 auto; padding: clamp(0.75rem, 2vw, 1.5rem); }

/* Briefly holds the page's scrollable height while a region collapses, so
   the browser never force-scrolls the content upward. Height is set from
   the script and is zero at rest. */
.collapse-spacer { height: 0; }

/* ---------------------------------------------------------
   Header
   --------------------------------------------------------- */
.app-header {
  display: flex; flex-wrap: wrap; align-items: center;
  justify-content: space-between; gap: 0.75rem 1rem;
  padding: 0.9rem clamp(0.75rem, 2vw, 1.5rem);
  border-bottom: 1px solid var(--line);
}

.brand { display: flex; align-items: center; gap: 1rem; min-width: 0; }

/* Account, edge, user and broker status, as the portal shows them */
.account-block {
  min-width: 0;
  font-size: 0.78rem;
  line-height: 1.45;
  opacity: 0.85;
}
.account-block > div { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#acct-name { font-weight: 700; opacity: 1; }

.brand-button {
  display: flex; align-items: center;
  border: 0; padding: 0; background: transparent;
  cursor: pointer; border-radius: 0.35rem;
}

.brand-logo { display: block; width: auto; height: 4.5rem; }
.brand-logo-dark { display: none; }
[data-theme="dark"] .brand-logo-light { display: none; }
[data-theme="dark"] .brand-logo-dark { display: block; }

.header-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }

/* Pill buttons. All header controls share one height so they can
   never drift apart when padding or font size changes. */
.header-button {
  display: inline-flex; align-items: center; gap: 0.55rem;
  height: var(--control-height);
  padding: 0 1.05rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  cursor: pointer;
  color: var(--ink); background: transparent;
  font-size: 0.88rem; font-weight: 600;
  transition: border-color 170ms ease, color 170ms ease;
}

.header-button:hover { border-color: var(--accent); color: var(--accent); }
.header-button .icon-glyph { width: 1.15rem; height: 1.15rem; stroke-width: 2; }

/* Both labels sit in the same grid cell, so the button is always as wide
   as the longer of the two and never resizes when the theme flips. Which
   one shows is decided by CSS from the theme attribute, so there is no
   JavaScript involved and no width change to chase. */
.theme-label { display: grid; }
.theme-label > span { grid-area: 1 / 1; text-align: left; }
.theme-label-light { visibility: hidden; }

[data-theme="dark"] .theme-label-dark { visibility: hidden; }
[data-theme="dark"] .theme-label-light { visibility: visible; }

.feedback-group {
  display: inline-flex; align-items: center; gap: 0.15rem;
  height: var(--control-height);
  padding: 0 0.45rem 0 0.85rem;
  border: 1px solid var(--line);
  border-radius: 999px;
}

/* "Thanks" replaces the word "Feedback" rather than sitting after it, so
   it adds no width at all - no empty gap while it is absent, and nothing
   moves when it appears. Both words share one grid cell, so the slot is
   always as wide as the longer of the two. */
.feedback-label {
  display: grid;
  margin-right: 0.4rem;
  font-size: 0.82rem;
  font-weight: 600;
  opacity: 0.85;
}

.feedback-label > span { grid-area: 1 / 1; white-space: nowrap; text-align: left; }
.feedback-label-thanks { visibility: hidden; color: var(--heading); }

.feedback-group.is-answered .feedback-label-default { visibility: hidden; }
.feedback-group.is-answered .feedback-label-thanks { visibility: visible; }

/* Unchosen faces are dimmed rather than nearly erased, and each sits on a
   faint disc so the paler ones have something to read against instead of
   bare white. */
.feedback-button {
  display: inline-grid; place-items: center;
  width: 1.85rem; height: 1.85rem;
  border: 0; border-radius: 50%; padding: 0;
  cursor: pointer;
  background: rgba(23, 33, 29, 0.07);
  opacity: 0.72;
  transition: opacity 150ms ease, transform 150ms ease, background-color 150ms ease;
}

[data-theme="dark"] .feedback-button { background: rgba(255, 255, 255, 0.08); }

.feedback-button:hover { opacity: 1; transform: translateY(-1px); }
.feedback-button[aria-pressed="true"] { opacity: 1; background: rgba(83,130,52,0.18); }
[data-theme="dark"] .feedback-button[aria-pressed="true"] { background: rgba(158,201,122,0.2); }
.feedback-button .mei-icon { width: 1.45rem; height: 1.45rem; }

/* The faces carry their own colours, which are pitched for a dark
   background. On the light theme the amber in particular disappears
   against white, so they are deepened rather than recoloured - the
   traffic-light meaning stays intact. */
:root:not([data-theme="dark"]) .feedback-button .mei-icon {
  filter: saturate(1.25) brightness(0.82);
}

/* The amber needs deepening further than the other two - at the shared
   setting it still only reached about 2.5:1 against white, under the 3:1
   usually asked of a graphic element. */
:root:not([data-theme="dark"]) .feedback-button[data-feedback="neutral"] .mei-icon {
  filter: saturate(1.5) brightness(0.7);
}

/* ---------------------------------------------------------
   Nav - scrolls sideways on small screens rather than stacking
   into a tall wall of buttons
   --------------------------------------------------------- */
.app-nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  padding: 0.8rem clamp(0.75rem, 2vw, 1.5rem) 0;
}

.nav-button {
  flex: 0 0 auto;
  text-align: center;
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  padding: 0.42rem 0.95rem;
  cursor: pointer;
  color: var(--on-accent); background: var(--accent);
  font-size: 0.86rem; font-weight: 600;
  transition: background-color 160ms ease;
}

.nav-button:hover { background: var(--accent-hover); }
.nav-button[aria-current="page"] { background: var(--accent-hover); box-shadow: inset 0 0 0 2px rgba(255,255,255,0.55); }

/* ---------------------------------------------------------
   Collapse to a dropdown

   A row of items that would otherwise wrap or scroll when the window
   narrows. The script measures the row once, and when it no longer
   fits it moves the very same buttons into a dropdown panel - they are
   moved, not duplicated, so there is only ever one of each.
   --------------------------------------------------------- */
.collapsible {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  gap: 0.3rem;
  min-width: 0;
}

/* Allowed to wrap now - the script decides when there are too many lines
   and only then swaps the row for the menu. */
.collapsible-row { display: flex; flex-wrap: wrap; gap: 0.3rem; min-width: 0; }
.collapsible.is-compact > .collapsible-row { display: none; }

.menu-trigger {
  display: none;
  align-self: flex-start;
  align-items: center;
  gap: 0.4rem;
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  padding: 0.42rem 0.8rem;
  cursor: pointer;
  color: var(--on-accent);
  background: var(--accent);
  font-size: 0.86rem;
  font-weight: 600;
  white-space: nowrap;
}

.collapsible.is-compact > .menu-trigger { display: inline-flex; }
.menu-trigger .icon-glyph { width: 0.95rem; height: 0.95rem; transition: transform 200ms ease; }

/* The navigation collapses to a single large hamburger, centred, rather
   than a worded button. Nothing about it changes when a section is chosen,
   so it cannot resize or shift anything around it. */
.menu-trigger-icon {
  align-self: center;
  justify-content: center;
  width: 3rem;
  height: 3rem;
  padding: 0;
  border-radius: var(--radius);
}

.menu-trigger-icon .icon-glyph {
  width: 1.7rem;
  height: 1.7rem;
  stroke-width: 2.4;
  transition: none;
}

/* The label text changes - "13 of 13 fields" becomes "9 of 13 fields",
   a section name becomes a longer one. A hidden copy of the widest text
   sits in the same grid cell so the button is always that wide and never
   resizes, which would shove whatever sits beside it. */
.menu-trigger-text { display: grid; }
.menu-trigger-text > span { grid-area: 1 / 1; text-align: left; white-space: nowrap; }
.menu-trigger-ghost { visibility: hidden; }
.menu-trigger[aria-expanded="true"] .icon-glyph { transform: rotate(90deg); }

/* The menu opens in the flow and pushes the page down, using the same
   grid-row animation as the accordions rather than floating over the
   content. Padding sits on the inner element, never on the one being
   animated, so a closed menu collapses to nothing. */
/* Sits on its own full-width row beneath the control, so the chips can
   use the whole box rather than only the column under the trigger. */
.menu-panel {
  flex: 1 1 100%;
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 260ms cubic-bezier(.2, .8, .2, 1);
}

.menu-panel.is-open { grid-template-rows: 1fr; }
.menu-panel > div { min-height: 0; overflow: hidden; }

/* Items wrap rather than stacking one per line - thirteen fields in a
   single column pushed half the page off the bottom. */
.menu-items {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  padding: 0.15rem 0 0.25rem;
}

/* ---------------------------------------------------------
   Accordion
   --------------------------------------------------------- */
/* Every level uses the same flex-column-with-gap pattern, so the space
   between two tiers and the space between a tier and its contents are
   always identical. */
.accordion-stack,
.tier-2-shell,
.tier-3-shell {
  display: flex;
  flex-direction: column;
  gap: var(--gap);
}

.accordion-region {
  display: grid; grid-template-rows: 0fr;
  transition: grid-template-rows 300ms cubic-bezier(.2,.8,.2,1);
}
.accordion-region.is-open { grid-template-rows: 1fr; }
.accordion-region > .region-inner { min-height: 0; overflow: hidden; }

/* Padding lives inside the clipped wrapper, never on it, so a closed
   panel collapses to exactly nothing and every gap on the page is the
   same --gap value. */

.accordion-row {
  display: flex; align-items: center; gap: 0.6rem;
  border-radius: var(--radius);
  background: var(--accent); color: var(--on-accent);
  transition: background-color 180ms ease;
}
.accordion-row:hover { background: var(--accent-hover); }

.tier-1-row { min-height: 3.3rem; padding: 0.4rem 0.7rem; }
.tier-2-shell { padding: var(--gap) 0 0 var(--indent); }
.tier-2-row { min-height: 3rem; padding: 0.35rem 0.65rem; }

/* The trailer bar carries the trailer name and its action buttons. */

.bar-actions {
  display: inline-flex;
  flex: 0 0 auto;
  gap: 0.15rem;
}

.bar-action {
  display: inline-grid;
  place-items: center;
  width: 1.9rem;
  height: 1.9rem;
  border: 0;
  border-radius: 0.35rem;
  padding: 0;
  cursor: pointer;
  color: var(--on-accent);
  background: rgba(255, 255, 255, 0.14);
  transition: background-color 150ms ease;
}

.bar-action:hover { background: rgba(255, 255, 255, 0.3); }
.bar-action .mei-icon,
.bar-action .icon-glyph { width: 1.05rem; height: 1.05rem; }

.tier-3-shell { padding: var(--gap) 0 0 var(--indent); }
.tier-3-row { min-height: 2.8rem; padding: 0.3rem 0.6rem; }
.panel-inner { padding-top: var(--gap); }

.toggle-button {
  display: inline-grid; flex: 0 0 auto; place-items: center;
  width: var(--toggle-size); height: var(--toggle-size);
  border: 0; border-radius: 50%; cursor: pointer;
  color: var(--on-accent); background: transparent;
  transition: background-color 170ms ease;
}
.toggle-button:hover { background: rgba(255,255,255,0.18); }
.toggle-button svg { width: 1.4rem; height: 1.4rem; transition: transform 240ms ease; }
.toggle-button[aria-expanded="true"] svg { transform: rotate(90deg); }

.row-label { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.tier-1-label { font-size: 1.1rem; font-weight: 700; }
.tier-2-label { font-size: 1rem; font-weight: 600; }
.tier-3-label { font-size: 0.94rem; font-weight: 700; }

.row-meta {
  flex: 0 0 auto; margin-left: auto;
  font-size: 0.8rem; font-weight: 600; opacity: 0.9;
  white-space: nowrap;
}

/* ---------------------------------------------------------
   Status panels
   Auto-fitting grid: as many columns as fit, one on a phone.
   --------------------------------------------------------- */
/* Columns rather than a grid. In a grid every row is as tall as its
   tallest panel, so a short panel leaves a block of dead space beneath it
   before the next row starts. Columns let each one sit directly under the
   one above, whatever their heights. */
.panel-grid {
  column-width: var(--panel-col);
  column-gap: var(--gap);
}

.panel-grid > .panel {
  break-inside: avoid;
  margin-bottom: var(--gap);
}

.panel {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--panel-bg);
  overflow: hidden;
}

/* Three columns with equal sides, so the title is centred in the panel
   rather than centred in whatever space the buttons leave over. Without
   it, panels with more buttons push their heading further left and the
   headings no longer line up with each other. */
.panel-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  gap: 0.4rem;
  padding: 0.15rem 0.45rem;
  background: var(--accent);
  color: var(--on-accent);
}

.panel-head > .panel-toggle { justify-self: start; }
.panel-head > .panel-actions { justify-self: end; }

/* A fourth tier in effect, so it behaves and animates like the others -
   same chevron, same grid-row transition, padding inside the clipped
   wrapper so a closed panel collapses to nothing. */
.panel-toggle {
  display: inline-grid;
  flex: 0 0 auto;
  place-items: center;
  width: 1.55rem;
  height: 1.55rem;
  border: 0;
  border-radius: 50%;
  padding: 0;
  cursor: pointer;
  color: var(--on-accent);
  background: transparent;
  transition: background-color 170ms ease;
}

.panel-toggle:hover { background: rgba(255, 255, 255, 0.2); }

.panel-toggle .icon-glyph {
  width: 1rem;
  height: 1rem;
  transition: transform 240ms ease;
}

.panel-toggle[aria-expanded="true"] .icon-glyph { transform: rotate(90deg); }

.panel-region {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 260ms cubic-bezier(.2, .8, .2, 1);
}

.panel-region.is-open { grid-template-rows: 1fr; }
.panel-region > .region-inner { min-height: 0; overflow: hidden; }

.panel-title {
  min-width: 0;
  text-align: center;
  font-size: 0.9rem; font-weight: 700;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.panel-actions {
  display: inline-flex; flex: 0 0 auto; gap: 0.1rem;
  padding-left: 0.5rem;
  border-left: 1px solid rgba(255,255,255,0.35);
}

.panel-action {
  display: inline-grid; place-items: center;
  width: 1.8rem; height: 1.8rem;
  border: 0; border-radius: 50%; padding: 0;
  cursor: pointer; color: var(--on-accent); background: transparent;
  transition: background-color 150ms ease;
}
.panel-action:hover { background: rgba(255,255,255,0.2); }
.panel-action .icon-glyph { width: 1rem; height: 1rem; }

.panel-body { padding: 0.3rem 0.6rem 0.6rem; }

/* Action buttons belong to the row they act on, in a column of their own
   at the end of that row - the same place the portal puts them. Keeping
   them in the flow is what stops them spilling over the row below. */
.pair-actions {
  display: inline-flex;
  flex: 0 0 auto;
  gap: 0.2rem;
  margin-left: auto;
}

.body-action {
  display: inline-grid;
  place-items: center;
  width: 1.75rem;
  height: 1.75rem;
  border: 1px solid var(--line);
  border-radius: 0.35rem;
  padding: 0;
  cursor: pointer;
  color: var(--accent);
  background: transparent;
  transition: background-color 150ms ease, color 150ms ease, border-color 150ms ease;
}

.body-action:hover { border-color: var(--accent); background: rgba(83,130,52,0.1); }
[data-theme="dark"] .body-action:hover { background: rgba(158,201,122,0.14); }
.body-action .mei-icon { width: 1.1rem; height: 1.1rem; }

/* Locked is a real state, so it is shown as one rather than only
   swapping the icon. */
.body-action[aria-pressed="true"] {
  color: var(--on-accent);
  background: var(--accent);
  border-color: var(--accent);
}



/* Label / value rows. Wraps to two lines rather than truncating,
   so nothing is ever unreadable on a narrow screen. */
.pair-row {
  display: flex; flex-wrap: wrap; align-items: baseline;
  gap: 0.25rem 0.75rem;
  padding: 0.32rem 0;
  border-bottom: 1px solid var(--rule);
  font-size: 0.87rem;
}
.pair-row:last-child { border-bottom: 0; }
.pair-label { flex: 1 1 8rem; font-weight: 600; }
.pair-value { flex: 1 1 8rem; overflow-wrap: anywhere; }
.pair-extra { flex: 1 1 9rem; font-size: 0.82rem; opacity: 0.75; overflow-wrap: anywhere; }

.status-ok { color: var(--ok); font-weight: 700; }
.status-fail { color: var(--fail); font-weight: 700; }
.status-none { opacity: 0.45; }

/* The negative left margin cancels the control's own border and padding,
   so the text inside the dropdown lines up with the plain text in the
   rows above and below it, rather than the box lining up. */
.site-select {
  width: 100%;
  max-width: 16rem;
  margin-left: calc(-0.45rem - 1px);
  padding: 0.1rem 1.4rem 0.1rem 0.45rem;
  border: 1px solid var(--line);
  border-radius: 0.35rem;
  color: var(--ink);
  background: var(--page-bg);
  font-size: 0.87rem;
  line-height: inherit;
}

.site-select:disabled {
  opacity: 0.55;
  cursor: not-allowed;
  background: var(--stripe);
}

/* Connections matrix - its own mini table */
.matrix { width: 100%; border-collapse: collapse; font-size: 0.85rem; }
.matrix th {
  padding: 0.3rem 0.35rem;
  border-bottom: 2px solid var(--accent);
  color: var(--heading);
  font-size: 0.7rem; letter-spacing: 0.05em; text-transform: uppercase;
  text-align: center;
}
.matrix th:first-child { text-align: left; }
.matrix td {
  padding: 0.28rem 0.35rem;
  border-bottom: 1px solid var(--rule);
  text-align: center;
}
.matrix td:first-child { text-align: left; font-weight: 400; }
.matrix tr:last-child td { border-bottom: 0; }

/* ---------------------------------------------------------
   Data tables
   --------------------------------------------------------- */
.data-table { border-bottom: 4px solid var(--accent); }

.table-title-bar {
  display: flex; align-items: center; gap: 0.75rem;
  padding: 0.35rem 0.55rem;
  border-radius: var(--radius) var(--radius) 0 0;
  background: var(--accent); color: var(--on-accent);
}

.table-title {
  flex: 1 1 auto; min-width: 0; text-align: center;
  font-size: 0.92rem; font-weight: 700;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.table-title-actions {
  display: inline-flex; flex: 0 0 auto; gap: 0.1rem;
  padding-left: 0.5rem; border-left: 1px solid rgba(255,255,255,0.35);
}

.title-action {
  display: inline-grid; place-items: center;
  width: 1.8rem; height: 1.8rem;
  border: 0; border-radius: 50%; padding: 0;
  cursor: pointer; color: var(--on-accent); background: transparent;
  transition: background-color 150ms ease;
}
.title-action:hover { background: rgba(255,255,255,0.2); }
.title-action .icon-glyph { width: 1rem; height: 1rem; }

.table-scroll { overflow-x: auto; border-top: 1px solid var(--line); }

.table-head, .table-row {
  display: grid;
  grid-template-columns: var(--table-columns);
  gap: 0.6rem;
  min-width: var(--table-min-width, 0);
  padding: 0.5rem 0.45rem;
}

.table-head {
  align-items: end;
  border-top: 3px solid var(--accent);
  border-bottom: 3px solid var(--accent);
  color: var(--heading);
  font-size: 0.72rem; font-weight: 700;
  letter-spacing: 0.05em; text-transform: uppercase;
}

.table-row { align-items: center; min-height: 2.4rem; font-size: 0.85rem; border-bottom: 1px solid var(--rule); }
.table-row:nth-child(even) { background: var(--stripe); }

.table-head > *, .table-row > * { min-width: 0; }

/* Column headings wrap onto a second line instead of being cut off.
   Body cells still truncate with an ellipsis, with the full value on
   hover, because row data varies far more in length. */
.table-head-cell {
  display: flex; align-items: flex-end; gap: 0.3rem;
  cursor: pointer;
}
.table-head-cell .cell-label {
  min-width: 0;
  overflow-wrap: anywhere;
}

.cell-text {
  min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Fixed-size arrow slot so the heading never shifts when sorting
   changes. Every column keeps an arrow; the active one is solid. */
.table-head-cell::after {
  display: inline-grid; place-items: center;
  width: 1.1em; height: 1em; flex: 0 0 auto;
  content: "\2191";
  color: var(--accent); font-size: 1em; font-weight: 800; line-height: 1;
  opacity: 0.4;
}
[data-theme="dark"] .table-head-cell::after { color: var(--heading); }
.table-head-cell[data-active="true"]::after { opacity: 1; }
.table-head-cell[data-sort-direction="desc"]::after { content: "\2193"; }

.actions-head { justify-self: end; }
.row-actions { display: inline-flex; justify-self: end; gap: 0.25rem; }

.row-action {
  display: inline-grid; place-items: center;
  border: 0; border-radius: 0.3rem; padding: 0;
  cursor: pointer; background: transparent;
  transition: transform 150ms ease, opacity 150ms ease;
}
.row-action:hover { transform: translateY(-1px); opacity: 0.8; }
.row-action .mei-icon { width: 1.3rem; height: 1.3rem; }

.table-empty { padding: 0.9rem 0.5rem; font-size: 0.85rem; opacity: 0.7; }

/* ---------------------------------------------------------
   Filters
   --------------------------------------------------------- */
.filter-stack { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-bottom: var(--gap); }

.filter-panel {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.15rem;
  padding: 0.28rem 0.45rem 0.28rem 0.8rem;
  border-radius: var(--radius);
  background: var(--accent);
}

.filter-label {
  margin-right: 0.4rem; color: var(--on-accent);
  font-size: 0.86rem; font-weight: 700; white-space: nowrap;
}

.radio-options { display: flex; flex-wrap: wrap; gap: 0.25rem; }
.radio-option { position: relative; display: inline-flex; align-items: center; cursor: pointer; }
.radio-option input { position: absolute; width: 1px; height: 1px; opacity: 0; }

.radio-indicator {
  display: inline-flex; align-items: center; gap: 0.45rem;
  padding: 0.24rem 0.7rem;
  border-radius: calc(var(--radius) - 0.25rem);
  color: var(--on-accent); font-size: 0.85rem; font-weight: 600;
  white-space: nowrap;
}
.radio-indicator::before {
  content: ""; flex: 0 0 auto;
  width: 0.68rem; height: 0.68rem;
  border: 1.5px solid var(--on-accent); border-radius: 50%;
  transition: background-color 160ms ease;
}
.radio-option input:checked + .radio-indicator { background: rgba(255,255,255,0.16); }
.radio-option input:checked + .radio-indicator::before {
  background: radial-gradient(circle, var(--on-accent) 0 38%, transparent 42%);
}

/* ---------------------------------------------------------
   Footer
   --------------------------------------------------------- */
.app-footer {
  display: flex; flex: 0 0 auto; flex-wrap: wrap;
  align-items: center; justify-content: center;
  gap: 0.35rem 2.5rem;
  padding: 0.7rem 1rem;
  background: var(--accent); color: var(--on-accent);
  font-size: 0.88rem;
}
.app-footer a { color: var(--on-accent); text-decoration: none; }
.app-footer a:hover { text-decoration: underline; }
.footer-item { display: inline-flex; gap: 0.4rem; white-space: nowrap; }
.footer-key { font-weight: 700; }

/* =========================================================
   NARROW SCREENS

   Below 760px each table row becomes its own labelled card.
   The grid and its column headings are dropped entirely, so
   nothing is squeezed, truncated or scrolled off the side -
   every value is shown with its column name beside it.
   ========================================================= */
@media (max-width: 760px) {
  .table-scroll { overflow-x: visible; }
  .table-head { display: none; }

  .table-row {
    display: block;
    min-width: 0;
    margin: 0 0 0.55rem;
    padding: 0.45rem 0.65rem;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--panel-bg);
  }
  .table-row:nth-child(even) { background: var(--stripe); }

  .table-row .cell-text {
    display: flex; justify-content: space-between; gap: 1rem;
    padding: 0.22rem 0;
    white-space: normal;
    overflow: visible;
    border-bottom: 1px solid var(--rule);
  }
  .table-row .cell-text:last-of-type { border-bottom: 0; }

  /* The column name for each value, taken from the header */
  .table-row .cell-text::before {
    content: attr(data-label);
    flex: 0 0 auto;
    color: var(--heading);
    font-size: 0.7rem; font-weight: 700;
    letter-spacing: 0.04em; text-transform: uppercase;
  }

  .table-row .cell-text.is-empty::after { content: "-"; opacity: 0.4; }

  .row-actions { justify-self: start; margin-top: 0.45rem; }

  .table-title { text-align: left; }
}


@media (max-width: 520px) {
  :root { --toggle-size: 2rem; }
  .app-header { justify-content: center; }
  .header-actions { width: 100%; justify-content: center; }
  .brand-logo { height: 3.4rem; }
  .account-block { display: none; }
  .feedback-label { display: none; }
  .pair-label, .pair-value, .pair-extra { flex: 1 1 100%; }
  .pair-actions { margin-left: 0; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
}

/* ================================================================
   Login pages
  
   Sits on top of medeikon-accordion.css and reuses its design
   tokens (colours, radius, control height, spacing), so the login
   screens share the portal's look. Only the login-specific pieces
   live here: the header, the centred card, the fields, the button
   and the error line.

   login.html and login-otp.html need no JavaScript. They are
   ordinary forms that post to the server, and the server outputs
   the red error line when the details are wrong.
   ================================================================ */

/* ---- header: logo + title, no portal controls (not signed in yet) ---- */
.login-header { justify-content: flex-start; }
.brand { display: flex; align-items: center; gap: 1rem; }
.brand-title {
  display: flex; flex-direction: column; line-height: 1.25;
  color: var(--ink); font-size: 1rem;
}
.brand-title .brand-name { font-weight: 700; }
.brand-user { font-size: 0.85rem; color: var(--heading); margin-top: 0.15rem; }

/* ---- the card ---- */
.login-main {
  flex: 1 0 auto;
  display: flex; align-items: flex-start; justify-content: center;
  padding: clamp(1.5rem, 6vh, 4rem) 1rem;
  background: var(--stripe);
}
.login-card {
  display: flex; flex-direction: column;
  width: 100%; max-width: 25rem;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--panel-bg); overflow: hidden;
  box-shadow: 0 1px 3px rgba(23, 33, 29, 0.08);
}
.login-card-title {
  background: var(--accent); color: var(--on-accent);
  padding: 0.7rem 1rem; font-weight: 700; text-align: center;
}
.login-card-body {
  display: flex; flex-direction: column; gap: 1rem;
  padding: 1.25rem;
}

/* ---- error line: the server outputs this when details are wrong ---- */
.login-error {
  margin: 0; color: var(--fail); font-weight: 600; font-size: 0.92rem;
}

/* ---- fields ---- */
.login-field { display: flex; flex-direction: column; gap: 0.35rem; }
.login-field label { font-weight: 600; font-size: 0.9rem; }
.login-field input {
  height: var(--control-height);
  padding: 0 0.7rem;
  border: 1px solid var(--line); border-radius: 0.4rem;
  background: var(--page-bg); color: var(--ink);
  font: inherit;
}
.login-field input:focus-visible {
  outline: 2px solid var(--focus); outline-offset: 1px;
  border-color: var(--focus);
}

/* ---- submit button: solid green, matches the portal ---- */
.login-button {
  align-self: flex-start;
  height: var(--control-height);
  padding: 0 1.4rem;
  border: none; border-radius: var(--radius);
  background: var(--accent); color: var(--on-accent);
  font: inherit; font-weight: 600; cursor: pointer;
  transition: background-color 160ms ease;
}
.login-button:hover { background: var(--accent-hover); }
.login-button:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
