/* AIR Centre Staff. Colours, type and chrome follow aircentre.org; the values
   sit on shadcn/ui's custom property names so components read one vocabulary.
   Where the site's pairing fails WCAG AA the value is adjusted and says why. */

@font-face {
  font-family: "Roboto";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("fonts/roboto-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Roboto";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("fonts/roboto-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Lora";
  font-style: normal;
  font-weight: 600 700;
  font-display: swap;
  src: url("fonts/lora-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Lora";
  font-style: normal;
  font-weight: 600 700;
  font-display: swap;
  src: url("fonts/lora-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

/* A subset holding only the glyphs ui.Icon is called with. A new icon means
   adding its name to icon_names (alphabetical) and running make icons:
   fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0&icon_names=arrow_forward,beach_access,calendar_month,cancel,check_circle,chevron_left,chevron_right,close,content_copy,dashboard,directions_car,download,edit,edit_calendar,error,event_busy,expand_more,fact_check,flag,groups,history,home,inbox,info,inventory_2,link,lock,lock_open,login,logout,manage_accounts,menu,more_time,notifications,person,person_add,person_off,restaurant,schedule,search,settings,today,verified,warning,weekend,wifi_off,work */
@font-face {
  font-family: "Material Symbols Outlined";
  font-style: normal;
  font-weight: 400;
  font-display: block;
  src: url("fonts/material-symbols-outlined.woff2") format("woff2");
}

/* Tokens. Brand values come from the site; the state colours pair each
   meaning with a surface and an ink that reach 4.5:1 on it in both schemes. */

:root {
  color-scheme: light dark;
  --radius-sm: 6px;
  --radius: 8px;
  --radius-lg: 10px;

  --brand: #ed6d26;
  --navy: #1a3a5c;
  --navy-deep: #0a192f;
  --teal: #00ccbb;
  --blue: #0077b5;

  --background: #f3f5f8;
  --foreground: #101828;
  --card: #ffffff;
  --card-foreground: #101828;
  --popover: #ffffff;
  --popover-foreground: #101828;
  /* White on the brand orange is 3.1:1, short of AA for body-size text, so
     filled buttons carry navy text (5.7:1). */
  --primary: var(--brand);
  --primary-foreground: var(--navy-deep);
  --secondary: #ffffff;
  --secondary-foreground: var(--navy);
  --muted: #eef1f5;
  --muted-foreground: #4a5568;
  --accent: #fde6d8;
  --accent-foreground: #7a3208;
  --destructive: #b42318;
  --destructive-foreground: #ffffff;
  --border: #dde2e9;
  --border-strong: #b3bdca;
  --input: #66768c;
  /* Orange marks the one action on a page and where you are, so links and
     the focus ring are ink blue: 7.5:1 on a card, 6.8:1 on the page. */
  --link: #0b5a85;
  --ring: #0b5a85;
  /* The ring around a filled orange button sits on the orange, where navy
     reaches 5.7:1. */
  --ring-on-primary: var(--navy-deep);
  --heading: var(--navy);
  --selected: #e7eef6;
  --selected-foreground: #12385c;
  --row-hover: #f6f8fa;
  --tile: #f3f5f8;
  --nav-hover-line: rgb(255 255 255 / 0.4);

  --success: #1e6b45;
  --success-surface: #e3f4ea;
  --warning: #8a4b00;
  --warning-surface: #fdf0d9;
  --danger: #a3271d;
  --danger-surface: #fbe4e1;
  --info: #0b5a85;
  --info-surface: #dff0fa;
  --leave: #0b5f59;
  --leave-surface: #d8f3ef;
  --neutral-surface: #e4eaf1;

  --chrome: var(--navy);
  --chrome-deep: var(--navy-deep);
  --chrome-foreground: #ffffff;
  --chrome-muted: rgb(255 255 255 / 0.72);
  --chrome-line: rgb(255 255 255 / 0.12);

  --shadow-sm: none;
  --shadow-md: 0 8px 24px rgb(10 25 47 / 0.12);

  --font-body: "Roboto", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-heading: "Lora", Georgia, "Times New Roman", serif;

  --nav-height: 3.75rem;
  --header-height: 4rem;

  /* Layout. Gutters and gaps are fluid between a phone and a desk; the
     measure caps a reading column; the frames cap each shell's main. */
  --gutter: clamp(1rem, 0.5rem + 2vw, 2.5rem);
  --gap: clamp(1rem, 0.5rem + 1vw, 1.5rem);
  --measure: 44rem;
  --spread: 88rem;
  --frame-app: 96rem;
  --frame-console: 124rem;
  --aside: 24rem;
  --list-pane: 18rem;
  --rail: 4.5rem;
}

@media (prefers-color-scheme: dark) {
  :root {
    --background: #0b1626;
    --foreground: #e2e8f0;
    --card: #12223a;
    --card-foreground: #e2e8f0;
    --popover: #12223a;
    --popover-foreground: #e2e8f0;
    --secondary: transparent;
    --secondary-foreground: #e2e8f0;
    --muted: #1a2d48;
    --muted-foreground: #a7b4c6;
    --accent: #3a2618;
    --accent-foreground: #f8c7a6;
    --destructive: #f07167;
    --destructive-foreground: #0a192f;
    --border: #233955;
    --border-strong: #3a5478;
    --input: #7d8ea6;
    --link: #8cc8f0;
    --ring: #8cc8f0;
    /* White is 3.1:1 on the orange and 17:1 on the dark page. */
    --ring-on-primary: #ffffff;
    --heading: #ffffff;
    --selected: #1c3352;
    --selected-foreground: #ffffff;
    --row-hover: #162a45;
    --tile: #0f1d33;

    --success: #86d9b0;
    --success-surface: #12382b;
    --warning: #f5c26b;
    --warning-surface: #3d2b0c;
    --danger: #f5a09a;
    --danger-surface: #46201d;
    --info: #8fd0f5;
    --info-surface: #0f3651;
    --leave: #7fe0d4;
    --leave-surface: #0f3e3a;
    --neutral-surface: #1f3556;

    --chrome: #0e2240;
    --chrome-deep: #061121;
    --chrome-line: rgb(255 255 255 / 0.1);

    --shadow-sm: none;
    --shadow-md: 0 8px 24px rgb(0 0 0 / 0.45);
  }

  .table-wrap {
    --scroll-shadow: rgb(0 0 0 / 0.5);
  }
}

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

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

body {
  margin: 0;
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.5;
  background: var(--background);
  color: var(--foreground);
}

.shell {
  display: flex;
  flex-direction: column;
  flex: 1;
}

h1,
h2,
h3 {
  font-family: var(--font-heading);
  font-weight: 700;
  line-height: 1.2;
  color: var(--heading);
  margin: 0 0 0.75rem;
  text-wrap: balance;
}

h1 {
  font-size: clamp(1.625rem, 1.35rem + 0.8vw, 1.875rem);
  letter-spacing: -0.01em;
}

h2 {
  font-size: 1.25rem;
  font-weight: 600;
}

h3 {
  font-size: 1.0625rem;
  font-weight: 600;
}

p {
  margin: 0 0 1rem;
}

a {
  color: var(--link);
  text-underline-offset: 0.18em;
  text-decoration-thickness: 1px;
}

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

/* A control reached by Tab, forwards or back, scrolls clear of the sticky
   header, the phone's fixed bar and the leave plan's sticky Save bar rather
   than landing under any of them (WCAG 2.4.11). */
html {
  --actionbar-height: 4.5rem;
  scroll-padding-top: calc(var(--header-height) + 0.5rem);
}

html:has(.leave-actionbar) {
  scroll-padding-bottom: calc(var(--actionbar-height) + 0.5rem);
}

/* The skip link's target is the page column, which takes focus without
   being a control, so it draws no ring around the whole page. */
.page:focus-visible {
  outline: none;
}

.icon {
  font-family: "Material Symbols Outlined";
  font-weight: normal;
  font-style: normal;
  font-size: 1.25em;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  display: inline-block;
  vertical-align: -0.25em;
  white-space: nowrap;
  direction: ltr;
  font-feature-settings: "liga";
  -webkit-font-smoothing: antialiased;
  flex: none;
}

h2 > .icon {
  color: var(--brand);
  margin-right: 0.125rem;
}

.visually-hidden,
.select-cell .check label {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.skip-link {
  position: absolute;
  left: 1rem;
  top: -3.5rem;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0.5rem 1rem;
  background: var(--card);
  color: var(--foreground);
  border-radius: var(--radius);
  z-index: 10;
}

.skip-link:focus {
  top: 0.5rem;
}

/* Header and footer: the site's navy chrome. The current tab carries the
   header's one orange mark. */

.shell-header {
  position: sticky;
  top: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 0.5rem 2rem;
  min-height: var(--header-height);
  padding: 0.5rem max(1.5rem, env(safe-area-inset-right)) 0.5rem max(1.5rem, env(safe-area-inset-left));
  background: var(--chrome);
  color: var(--chrome-foreground);
  border-bottom: 1px solid var(--chrome-line);
}

.shell-header :focus-visible {
  outline-color: var(--chrome-foreground);
}

.brand {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-height: 44px;
  color: var(--chrome-foreground);
  text-decoration: none;
}

.brand img {
  height: 44px;
  width: auto;
}

.brand span {
  font-family: var(--font-heading);
  font-size: 1.25rem;
  font-weight: 600;
  letter-spacing: 0.01em;
}

.shell-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 0.25rem;
  flex: 1;
}

.shell-nav a {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  min-height: 44px;
  padding: 0 0.75rem;
  color: var(--chrome-muted);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  border-radius: var(--radius-sm);
  transition: background-color 150ms ease-out, color 150ms ease-out;
}

.shell-nav a .icon {
  font-size: 1.25rem;
  opacity: 0.85;
}

.shell-nav a:hover,
.shell-nav a[aria-current="page"] {
  color: var(--chrome-foreground);
}

/* On a desk the tabs run the header's full height, so the underline sits on
   its bottom edge; hover's lighter line never reads as the current one. */
@media (min-width: 48.0625rem) {
  .shell-header {
    padding-block: 0;
  }

  .shell-nav {
    align-self: stretch;
  }

  .shell-nav a {
    position: relative;
    min-height: var(--header-height);
    border-radius: 0;
  }

  .shell-nav a::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 3px;
    background: transparent;
    transition: background-color 150ms ease-out;
  }

  .shell-nav a:hover::after {
    background: var(--nav-hover-line);
  }

  .shell-nav a[aria-current="page"]::after {
    background: var(--brand);
  }
}

/* Sign-out keeps the right edge on setup too, where no nav fills the
   middle. */
.shell-header > form:last-child {
  margin-left: auto;
}

.shell-header .btn-signout {
  color: var(--chrome-foreground);
  border-color: rgb(255 255 255 / 0.35);
  background: transparent;
  min-height: 40px;
  padding: 0.375rem 1rem;
  font-size: 0.9375rem;
}

.shell-header .btn-signout:hover {
  border-color: var(--brand);
  color: var(--chrome-foreground);
}

.avatar {
  flex: none;
  border-radius: 50%;
  object-fit: cover;
  background: var(--muted);
}

/* The avatar opens its panel under the header's right edge. */
.account-menu {
  position: relative;
  margin-left: auto;
}

/* The trigger takes the nav links' hover fill, and its chevron turns as the
   console menu's does. */
.account-menu > summary {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 44px;
  padding: 0 0.25rem 0 0.375rem;
  list-style: none;
  cursor: pointer;
  border-radius: var(--radius-sm);
  color: var(--chrome-foreground);
  transition: background-color 150ms ease-out;
}

.account-menu > summary:hover,
.account-menu[open] > summary {
  background: rgb(255 255 255 / 0.07);
}

/* Preferences open inside the menu, so it carries the current tab's mark. */
.account-menu > summary.current {
  box-shadow: inset 0 -3px 0 var(--brand);
}

.account-name {
  max-width: 9rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.9375rem;
  font-weight: 500;
}

.account-menu > summary .icon {
  color: var(--chrome-muted);
  transition: transform 150ms ease-out;
}

.account-menu[open] > summary .icon {
  transform: rotate(180deg);
}

/* Below a wide desk the six nav links need the name's width. It stays as
   the trigger's accessible name, since the avatar's alt is empty. */
@media (max-width: 67.5rem) {
  .account-name {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

.account-menu > summary::-webkit-details-marker {
  display: none;
}

.account-menu > summary .avatar {
  box-shadow: 0 0 0 2px rgb(255 255 255 / 0.35);
  transition: box-shadow 150ms ease-out;
}

.account-menu > summary:hover .avatar,
.account-menu[open] > summary .avatar {
  box-shadow: 0 0 0 2px var(--brand);
}

.account-panel {
  position: absolute;
  right: 0;
  top: calc(100% + 0.5rem);
  z-index: 6;
  display: grid;
  min-width: 15rem;
  max-width: calc(100vw - 2rem);
  padding: 0.5rem;
  background: var(--popover);
  color: var(--popover-foreground);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
}

.account-who {
  display: grid;
  gap: 0.125rem;
  margin: 0 0 0.5rem;
  padding: 0.5rem 0.75rem 0.75rem;
  border-bottom: 1px solid var(--border);
  overflow-wrap: anywhere;
}

.account-who span {
  font-size: 0.875rem;
  color: var(--muted-foreground);
}

.account-panel a,
.account-panel button {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  min-height: 44px;
  padding: 0 0.75rem;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}

.account-panel a:hover,
.account-panel button:hover {
  background: var(--muted);
}

.account-panel a[aria-current="page"] {
  background: var(--accent);
  color: var(--accent-foreground);
  font-weight: 700;
}

.account-panel :focus-visible {
  outline-color: var(--ring);
}

.account-panel .icon {
  color: var(--muted-foreground);
}

.person-link {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
}

/* The avatar lines up with the heading's first line, which stays put when
   a narrow page stacks the heading's nav under it. */
.person-title {
  display: flex;
  align-items: flex-start;
  gap: 1rem;
}

.person-title > .page-head {
  flex: 1;
}

/* Frames. main is the frame and .page the content column; each is a size
   container, so the primitives below measure the column they sit in, never
   the viewport. In the app every child of .page is a centred reading column
   unless it lays panes or breaks out; in the console .page fills the width
   beside the section nav. */

main {
  container: frame / inline-size;
  width: 100%;
  max-width: var(--frame-console);
  margin: 0 auto;
  padding: var(--gap) var(--gutter) 3.5rem;
  flex: 1;
}

.page {
  container: page / inline-size;
  min-width: 0;
}

.shell-app main {
  max-width: var(--frame-app);
}

.shell-app .page {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.shell-app .page > * {
  width: 100%;
  max-width: var(--measure);
}

.shell-app .page > :is(.panes, .breakout) {
  max-width: var(--spread);
}

/* A page that lays panes or breaks out is a wide page: its head and toasts
   line up with the panes rather than floating in a centred column. */
.shell-app .page:has(> :is(.panes, .breakout)) > * {
  max-width: var(--spread);
}

.shell-console .page,
.shell-super .page {
  max-width: 100rem;
}

/* A card of forms alone on a console page keeps its fields at a readable
   width; a form beside its results is an aside, sized by the panes. A card
   standing in for a form, such as Deactivate on one's own account, keeps
   the same width. */
:is(.shell-console, .shell-super) :is(.page, .detail) > :is(.card:has(form), .card-narrow) {
  max-width: 48rem;
}

.shell-footer {
  padding: 1.25rem var(--gutter);
  color: var(--muted-foreground);
  border-top: 1px solid var(--border);
  font-size: 0.8125rem;
}

.shell-footer p {
  max-width: var(--frame-console);
  margin: 0 auto;
}

/* Pages shown outside a shell: errors and the signed-out screen. */

/* The body is a 100dvh flex column; growing into it keeps the gradient to
   the bottom edge on a phone, where 100vh and the visible height differ. */
.standalone {
  flex: 1 0 auto;
  display: grid;
  place-items: center;
  min-height: 100dvh;
  padding: 1.5rem 1rem;
  background: var(--chrome-deep);
  background-image: radial-gradient(ellipse at top, var(--navy) 0%, var(--chrome-deep) 65%);
}

.standalone-card {
  width: min(26rem, 100%);
  padding: 2rem 1.75rem;
  text-align: center;
  background: var(--card);
  color: var(--card-foreground);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
}

.standalone-logo {
  height: 72px;
  width: auto;
  margin-bottom: 0.5rem;
}

.standalone-brand {
  font-family: var(--font-heading);
  font-weight: 600;
  color: var(--muted-foreground);
  margin-bottom: 1.25rem;
}

.standalone h1 {
  font-size: 1.5rem;
}

.standalone .btn {
  width: 100%;
}

/* Google's sign-in button: its own neutral fill, outline and G, which its
   branding asks for in place of the app's colours. Two classes, so it wins
   over the .btn rules later in the file. */
.btn.btn-google {
  gap: 0.75rem;
  background: #fff;
  color: #1f1f1f;
  border: 1px solid #747775;
  font-weight: 500;
}

.btn.btn-google:hover {
  background: #f2f2f2;
}

.btn-google svg {
  flex: none;
  width: 20px;
  height: 20px;
}

@media (prefers-color-scheme: dark) {
  .btn.btn-google {
    background: #131314;
    color: #e3e3e3;
    border-color: #8e918f;
  }

  .btn.btn-google:hover {
    background: #252526;
  }
}

.page-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem 1.5rem;
  margin-bottom: 1rem;
}

.page-head h1 {
  margin: 0;
}

.card {
  container-type: inline-size;
  background: var(--card);
  color: var(--card-foreground);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 1.5rem;
  margin-bottom: 1.25rem;
  box-shadow: var(--shadow-sm);
}

.card > :last-child {
  margin-bottom: 0;
}

.card > h2:first-child {
  margin-bottom: 1rem;
}

.lead {
  font-size: 1.0625rem;
  color: var(--muted-foreground);
  max-width: 60ch;
  margin-bottom: 1.5rem;
}

.muted {
  color: var(--muted-foreground);
}

.divider {
  height: 1px;
  border: 0;
  margin: 1.5rem 0;
  background: linear-gradient(to right, transparent, var(--brand), transparent);
  opacity: 0.6;
}

.steps {
  padding-left: 1.25rem;
}

.steps li {
  margin-bottom: 0.75rem;
  padding-left: 0.25rem;
}

.steps li::marker {
  font-family: var(--font-heading);
  font-weight: 700;
  color: var(--brand);
}

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 1.5rem;
}

.download-note {
  display: none;
  align-items: center;
  margin: 0;
}

.download-note.shown {
  display: flex;
}

.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  margin: 0;
  padding: 1.5rem 1rem;
  text-align: center;
  color: var(--muted-foreground);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius);
}

.empty .icon {
  font-size: 2rem;
  opacity: 0.7;
}

/* Layout primitives. Cluster wraps a row; grid fills a row with equal tiles
   no narrower than --min; panes lays an aside beside a main pane when the
   page column has room and stacks them in source order when it has not;
   breakout lets a calendar leave the reading column; a list pane is the list
   half of a list-detail page and only exists on a wide screen. */

.cluster {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--cluster-gap, 0.75rem);
}

.toolbar {
  --cluster-gap: var(--gap);
  justify-content: space-between;
  align-items: flex-end;
  margin-bottom: 1.25rem;
}

.toolbar > * {
  margin: 0;
}

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(var(--min, 18rem), 100%), 1fr));
  gap: var(--gap);
}

.panes {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  column-gap: var(--gutter);
  align-items: start;
}

.pane-aside,
.pane-main {
  container-type: inline-size;
  min-width: 0;
}

@container page (width >= 56rem) {
  .panes {
    grid-template-columns: var(--aside) minmax(0, 1fr);
  }

  .panes:has(> .pane-main:first-child) {
    grid-template-columns: minmax(0, 1fr) var(--aside);
  }

  .pane-aside.pinned {
    position: sticky;
    top: calc(var(--header-height) + var(--gap));
  }
}

/* Stacked on a phone, the month's totals read before the 30 day rows rather
   than after them; .day-list picks out the month page's panes alone. On a
   wide screen the aside already sits beside the list, so its source order,
   which the :has(> .pane-main:first-child) rule above depends on, is
   untouched. */
@container page (width < 56rem) {
  .panes:has(.day-list) > .pane-aside.pinned {
    order: -1;
  }
}

.list-pane {
  display: none;
}

.detail {
  container: page / inline-size;
  min-width: 0;
}

/* The list-detail grid needs the frame to hold the list beside a detail
   column at least as wide as the reading measure, after the console's nav. */
@container frame (width >= 60rem) {
  .shell-app .page:has(> .list-pane) {
    display: grid;
    grid-template-columns: var(--list-pane) minmax(0, 52rem);
    justify-content: center;
    column-gap: var(--gutter);
    align-items: start;
  }

  .shell-app .page:has(> .list-pane) > * {
    max-width: none;
  }

  .shell-app .list-pane {
    display: block;
  }
}

@container frame (width >= 84rem) {
  .shell-super .page:has(> .list-pane) {
    display: grid;
    grid-template-columns: var(--list-pane) minmax(0, 1fr);
    column-gap: var(--gutter);
    align-items: start;
  }

  .shell-super .list-pane {
    display: block;
  }

  .shell-super .pane-select {
    display: none;
  }
}

/* Where the list pane does not fit, a header select (pane-select) stands in
   for it. The console's team list needs more room than super's accounts
   before the detail column stops feeling cramped, so it gives way later. */
.pane-select {
  margin: 1rem 0 1.25rem;
}

.pane-select form {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.75rem;
}

.pane-select .field {
  flex: 1 1 12rem;
  margin: 0;
}

@container frame (width >= 100rem) {
  .shell-console .page:has(> .list-pane) {
    display: grid;
    grid-template-columns: var(--list-pane) minmax(0, 1fr);
    column-gap: var(--gutter);
    align-items: start;
  }

  .shell-console .list-pane {
    display: block;
  }

  .shell-console .pane-select {
    display: none;
  }
}

.list-pane {
  position: sticky;
  top: calc(var(--header-height) + var(--gap));
  /* Same box the shell itself fills (.shell min-height above), so a short
     list still reaches as far down as a tall detail card beside it. */
  min-height: calc(100dvh - var(--header-height) - var(--gap) * 2);
  max-height: calc(100dvh - var(--header-height) - var(--gap) * 2);
  overflow-y: auto;
  margin: 0;
  padding: 0.25rem;
}

.list-pane > p {
  margin: 0.25rem 0 0.5rem 0.75rem;
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted-foreground);
}

.list-pane a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  min-height: 44px;
  padding: 0.375rem 0.75rem;
  border-left: 3px solid transparent;
  border-radius: var(--radius-sm);
  color: var(--foreground);
  font-size: 0.9375rem;
  text-decoration: none;
  font-variant-numeric: tabular-nums;
}

.list-pane a > span:first-child {
  font-weight: 500;
}

.list-pane a:hover {
  background: var(--muted);
  color: var(--heading);
}

.list-pane a[aria-current="page"] {
  background: var(--selected);
  border-left-color: var(--brand);
  color: var(--selected-foreground);
  font-weight: 700;
}

.list-pane .badge {
  font-size: 0.75rem;
}

.list-pane .day-off {
  color: var(--muted-foreground);
}

/* Buttons. 44px targets, for thumbs outdoors. */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 44px;
  padding: 0.625rem 1.5rem;
  font: inherit;
  font-weight: 500;
  line-height: 1.2;
  border: 2px solid transparent;
  border-radius: var(--radius);
  cursor: pointer;
  text-decoration: none;
  transition: background-color 150ms ease-out, border-color 150ms ease-out, color 150ms ease-out, transform 100ms ease-out;
}

.btn:active:not(:disabled) {
  transform: translateY(1px);
}

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

.btn-primary {
  background: var(--primary);
  color: var(--primary-foreground);
  box-shadow: var(--shadow-sm);
}

.btn-primary:focus-visible {
  outline-color: var(--ring-on-primary);
}

/* 88% keeps navy on orange at 4.52:1; darker fails the ruling. */
.btn-primary:hover:not(:disabled) {
  background: color-mix(in srgb, var(--primary) 88%, black);
}

.btn-secondary {
  background: var(--secondary);
  color: var(--secondary-foreground);
  border-color: var(--input);
}

.btn-secondary:hover:not(:disabled) {
  border-color: var(--link);
  color: var(--link);
}

.btn-ghost {
  background: transparent;
  color: inherit;
  padding-inline: 0.75rem;
}

.btn-ghost:hover:not(:disabled) {
  background: var(--muted);
}

.btn-danger {
  background: var(--destructive);
  color: var(--destructive-foreground);
}

.btn-icon {
  min-width: 44px;
  padding: 0.5rem;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
  margin-bottom: 1.25rem;
}

.field label,
fieldset legend {
  font-weight: 500;
}

.invite-link-row {
  display: flex;
  align-items: flex-end;
  gap: 0.75rem;
}

.invite-link-row .field {
  flex: 1;
  min-width: 0;
  margin-bottom: 0;
}

fieldset {
  border: 0;
  padding: 0;
  margin: 0 0 1.25rem;
  min-width: 0;
}

fieldset legend {
  margin-bottom: 0.5rem;
  padding: 0;
}

.input {
  width: 100%;
  min-height: 44px;
  padding: 0.5rem 0.75rem;
  font: inherit;
  color: var(--foreground);
  background: var(--card);
  border: 1px solid var(--input);
  border-radius: var(--radius);
  transition: border-color 150ms ease-out;
}

.input:hover {
  border-color: var(--foreground);
}

.textarea {
  resize: vertical;
  line-height: 1.4;
}

.input[aria-invalid="true"] {
  border: 2px solid var(--destructive);
}

.field-hint {
  margin: 0;
  font-size: 0.875rem;
  color: var(--muted-foreground);
}

/* Hints between controls, outside any field: a correction form's note on
   empty hours before the reason field. */
form > .field-hint + .field,
form > .field-hint + .check {
  margin-top: 1rem;
}

.time-grid + .check {
  margin-bottom: 0.5rem;
}

.field-error {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  margin: 0;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--destructive);
}

.check {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-height: 44px;
}

.checkbox {
  flex: none;
  width: 1.25rem;
  height: 1.25rem;
  margin: 0;
  accent-color: var(--link);
}

.choices {
  display: grid;
  gap: 0.5rem;
}

.choice {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  padding: 0.75rem 1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--card);
}

.reminder {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 0.75rem;
  border-bottom: 1px solid var(--border);
  padding: 0.25rem 0;
}

.reminder:last-child {
  border-bottom: 0;
}

.reminder .field {
  margin: 0;
}

.reminder .field .input {
  width: 8rem;
}

.reminder .field label {
  font-size: 0.8125rem;
  color: var(--muted-foreground);
}

.dialog {
  width: min(32rem, calc(100vw - 2rem));
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--popover);
  color: var(--popover-foreground);
  box-shadow: 0 10px 30px rgb(10 25 47 / 0.35);
}

.dialog::backdrop {
  background: rgb(10 25 47 / 0.55);
  backdrop-filter: blur(4px);
}

.dialog-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1rem 1rem 0 1.5rem;
}

.dialog-head h2 {
  margin: 0;
}

.dialog-body {
  padding: 1rem 1.5rem 1.5rem;
}

/* Tables: dense, tabular figures, legible on a desk screen. */

/* Wider than its column the table scrolls sideways; the edge shadows say so
   where scrollbars are hidden. The card-coloured layers scroll with the
   content and cover the shadows at either end. */
/* Positioned so it is the containing block of the visually hidden text in
   its cells: an absolute box escapes the overflow clip of a scroller that is
   not its containing block, and widens the page instead. */
.table-wrap {
  --scroll-shadow: rgb(10 25 47 / 0.16);
  position: relative;
  overflow-x: auto;
  background:
    linear-gradient(to right, var(--card) 40%, transparent) left / 3rem 100% no-repeat local,
    linear-gradient(to left, var(--card) 40%, transparent) right / 3rem 100% no-repeat local,
    linear-gradient(to right, var(--scroll-shadow), transparent) left / 1rem 100% no-repeat scroll,
    linear-gradient(to left, var(--scroll-shadow), transparent) right / 1rem 100% no-repeat scroll,
    var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  margin-bottom: 1.25rem;
  box-shadow: var(--shadow-sm);
  container-type: inline-size;
}

.table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.875rem;
  font-variant-numeric: tabular-nums;
  color: var(--card-foreground);
}

/* Lora's tabular figures also widen the space glyph, which the table sets
   for its numbers; the caption is words. */
.table caption {
  padding: 1rem 1.25rem 0.75rem;
  text-align: left;
  font-family: var(--font-heading);
  font-variant-numeric: normal;
  font-weight: 600;
  font-size: 1.125rem;
  color: var(--heading);
}

.table th,
.table td {
  padding: 0.625rem 0.875rem;
  text-align: left;
  white-space: nowrap;
  border-top: 1px solid var(--border);
  vertical-align: top;
}

/* Headings wrap so a wordy column (Portuguese runs long) takes the width of
   its values, not of its name. */
.table thead th {
  position: sticky;
  top: 0;
  background: var(--card);
  color: var(--muted-foreground);
  font-weight: 600;
  font-size: 0.8125rem;
  line-height: 1.25;
  white-space: normal;
  vertical-align: bottom;
  border-bottom: 1px solid var(--border-strong);
}

.table tbody tr:hover {
  background: var(--row-hover);
}

.table tbody tr:last-child td {
  border-bottom: 0;
}

/* The last column holds whatever runs long, a note or a stamp summary, so
   it wraps instead of pushing the table into a sideways scroll. */
.table td:last-child {
  white-space: normal;
  min-width: 12rem;
}

/* A trailing button, disclosure or badge is as wide as itself; the floor
   is for a note. */
.table td:last-child:has(form, details, .badge) {
  min-width: 0;
}

/* A prose value (a holiday's name, a correction's reason) wraps where it
   sits, so a narrow column fits without a sideways scroll. */
.table td:has(> .cell-wrap) {
  white-space: normal;
  min-width: 8rem;
}

/* Labelled stamps wrap between stamps, never inside one. */
.table td:has(> .day-times) {
  white-space: normal;
  min-width: 10rem;
}

/* A link alone in a cell (a name, a count, a date) keeps the row's height
   as its tap target; the negative margin leaves the row where it was. */
.table td > a:only-child {
  display: inline-block;
  padding-block: 0.625rem;
  margin-block: -0.625rem;
}

.table td > a.person-link {
  display: inline-flex;
}

/* Narrower than a desk column the first column freezes, so a row keeps its
   name while the rest scrolls; the hairline and shadow on its right edge say
   the rest is there. */
@container (width < 40rem) {
  .table th:first-child,
  .table td:first-child {
    position: sticky;
    left: 0;
    z-index: 1;
    background: var(--card);
    box-shadow: inset -1px 0 0 var(--border), 4px 0 6px -4px var(--scroll-shadow);
  }

  .table thead th:first-child {
    z-index: 2;
    background: var(--muted);
  }

  .table tbody tr:hover td:first-child {
    background: color-mix(in srgb, var(--muted) 55%, var(--card));
  }
}

/* A reflowed table: each row a bordered block, each cell headed by its
   column's name, the first cell as the block's title. The head stays in the
   tree for assistive technology. The threshold is wider than the frozen
   column's, since a row with a form needs its buttons in view. */
@container (width < 48rem) {
  .reflow .table,
  .reflow .table tbody,
  .reflow .table tr,
  .reflow .table td {
    display: block;
    white-space: normal;
  }

  .reflow .table caption {
    display: block;
  }

  .reflow .table thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
  }

  .reflow .table tr {
    padding: 0.75rem 1rem 1rem;
    border-top: 1px solid var(--border);
  }

  .reflow .table tbody tr:hover {
    background: transparent;
  }

  .reflow .table td {
    padding: 0.25rem 0;
    border: 0;
  }

  .reflow .table td:first-child {
    position: static;
    box-shadow: none;
    padding-bottom: 0.375rem;
    font-size: 1rem;
    font-weight: 700;
    color: var(--heading);
  }

  .reflow .table td:not(:first-child)::before {
    content: attr(data-label);
    display: block;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--muted-foreground);
  }

  .reflow .table td:empty {
    display: none;
  }

  .reflow .table td > a:only-child {
    display: inline-flex;
    align-items: center;
    min-height: 40px;
    padding-block: 0;
    margin-block: 0;
  }

  .reflow .table form {
    margin-top: 0.5rem;
  }

  .reflow .table form .input {
    min-width: 0;
    width: 100%;
  }

  .reflow .table form .field {
    flex: 1 1 12rem;
  }
}

/* Close's rows lead with a checkbox, which would otherwise take the stacked
   block's title; it sits at the name's end instead. */
@container (width < 30rem) {
  .stack .table td:first-child:has(> .select-cell) {
    float: right;
    padding: 0.25rem 0 0;
  }

  .stack .table td:has(> .select-cell) + td {
    font-size: 1rem;
    font-weight: 700;
    color: var(--heading);
  }

  .stack .table td:has(> .select-cell) + td::before {
    content: none;
  }
}

/* A dense table stacks the same way on a phone, where scrolling sideways
   would hide most of a row; above that it scrolls with its first column
   frozen. TestTables_stackOnAPhoneTheWayFormTablesReflow in test/lint/
   holds this block to the reflow block above. */
@container (width < 30rem) {
  .stack .table,
  .stack .table tbody,
  .stack .table tr,
  .stack .table td {
    display: block;
    white-space: normal;
  }

  .stack .table caption {
    display: block;
  }

  .stack .table thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
  }

  .stack .table tr {
    padding: 0.75rem 1rem 1rem;
    border-top: 1px solid var(--border);
  }

  .stack .table tbody tr:hover {
    background: transparent;
  }

  .stack .table td {
    padding: 0.25rem 0;
    border: 0;
  }

  .stack .table td:first-child {
    position: static;
    box-shadow: none;
    padding-bottom: 0.375rem;
    font-size: 1rem;
    font-weight: 700;
    color: var(--heading);
  }

  .stack .table td:not(:first-child)::before {
    content: attr(data-label);
    display: block;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--muted-foreground);
  }

  .stack .table td:empty {
    display: none;
  }

  .stack .table td > a:only-child {
    display: inline-flex;
    align-items: center;
    min-height: 40px;
    padding-block: 0;
    margin-block: 0;
  }

  .stack .table form {
    margin-top: 0.5rem;
  }

  .stack .table form .input {
    min-width: 0;
    width: 100%;
  }

  .stack .table form .field {
    flex: 1 1 12rem;
  }
}

/* In a table row the summary sits on the row's text line; the negative
   margin keeps its 44px target without growing the row. */
.table details > summary {
  padding-block: 0.625rem;
  margin-block: -0.625rem;
}

/* Forms inside a cell: absences' inline resize, approvals' decisions. */

/* A closed disclosure's form still counts toward the column's width in a
   table's layout, so it leaves the layout until the row is opened. */
.table details:not([open]) > form {
  display: none;
}

.table form {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.5rem;
}

.table form .field {
  margin: 0;
  gap: 0.25rem;
}

/* A decision's buttons take a line of their own under its reason. */
.table form .actions {
  flex-basis: 100%;
  margin-top: 0;
  gap: 0.5rem;
}

.table form .field label {
  font-size: 0.75rem;
  color: var(--muted-foreground);
}

.table form .input {
  min-height: 40px;
  width: auto;
  min-width: 9rem;
}

.table form .btn {
  min-height: 40px;
  padding: 0.5rem 1rem;
}

/* The tabs wrap rather than scroll, so a narrow phone never hides one
   off-screen with nothing to say it is there. */
.tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
  border-bottom: 1px solid var(--border);
  margin-bottom: 1.5rem;
  overflow-x: auto;
  scrollbar-width: none;
}

.tabs a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 1rem;
  color: var(--muted-foreground);
  font-weight: 500;
  text-decoration: none;
  white-space: nowrap;
  border-bottom: 3px solid transparent;
  margin-bottom: -1px;
  transition: color 150ms ease-out, border-color 150ms ease-out;
}

.tabs a:hover {
  color: var(--foreground);
  border-bottom-color: var(--border-strong);
}

.tabs a[aria-current="page"] {
  color: var(--heading);
  font-weight: 700;
  border-bottom-color: var(--brand);
}

/* Chips: a filter that wraps, so every choice stays in view on a phone. */

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 1.25rem;
}

.chips a {
  display: inline-flex;
  align-items: center;
  min-height: 36px;
  padding: 0 0.875rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--card);
  color: var(--foreground);
  font-size: 0.9375rem;
  font-weight: 500;
  text-decoration: none;
  font-variant-numeric: tabular-nums;
  transition: border-color 150ms ease-out, background-color 150ms ease-out;
}

.chips a:hover {
  border-color: var(--link);
  color: var(--link);
}

.chips a[aria-current="page"] {
  background: var(--heading);
  border-color: var(--heading);
  color: var(--card);
  font-weight: 700;
}

/* Console sections: a disclosure headed by the current section, which the
   desk layout below unfolds into a sidebar. */

.console-nav {
  margin-bottom: 1.5rem;
}

.console-menu > summary {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 44px;
  padding: 0.375rem 0.75rem 0.375rem 1rem;
  list-style: none;
  cursor: pointer;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  font-weight: 500;
  color: var(--muted-foreground);
}

.console-menu > summary::-webkit-details-marker {
  display: none;
}

.console-menu > summary .icon:first-child {
  color: var(--brand);
}

.console-menu > summary .icon:last-child {
  margin-left: auto;
  transition: transform 150ms ease-out;
}

.console-menu[open] > summary .icon:last-child {
  transform: rotate(180deg);
}

.console-current {
  font-weight: 600;
  color: var(--heading);
}

.console-current:empty {
  display: none;
}

.console-groups {
  display: grid;
  gap: 0.25rem 1.5rem;
  margin-top: 0.5rem;
  padding: 0.75rem 0.5rem;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
}

.console-group > p {
  margin: 0.5rem 0 0.25rem 0.75rem;
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted-foreground);
}

.console-group > a {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  min-height: 44px;
  padding: 0.375rem 0.75rem;
  border-left: 3px solid transparent;
  border-radius: var(--radius-sm);
  color: var(--foreground);
  font-size: 0.9375rem;
  font-weight: 500;
  text-decoration: none;
  transition: background-color 150ms ease-out, color 150ms ease-out;
}

.console-group > a .icon {
  font-size: 1.25rem;
  color: var(--muted-foreground);
}

.console-group > a:hover {
  background: var(--selected);
  color: var(--heading);
}

.console-group > a[aria-current="page"] {
  background: var(--card);
  border-left-color: var(--brand);
  box-shadow: inset 0 0 0 1px var(--border);
  color: var(--selected-foreground);
  font-weight: 700;
}

.console-group > a[aria-current="page"] .icon {
  color: var(--selected-foreground);
}

/* Toasts and status: every state has an icon and words, never colour alone. */

.toast {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.75rem 1rem;
  margin-bottom: 1.25rem;
  border-radius: var(--radius);
  border-left: 4px solid currentColor;
  font-weight: 500;
}

.toast-success {
  background: var(--success-surface);
  color: var(--success);
}

.toast-info {
  background: var(--info-surface);
  color: var(--info);
}

.toast-error {
  background: var(--danger-surface);
  color: var(--danger);
}

.toast a {
  color: inherit;
  font-weight: 700;
}

/* A hairline in the badge's own ink gives its tint an edge on a white card. */
.badge {
  box-shadow: inset 0 0 0 1px color-mix(in srgb, currentColor 28%, transparent);
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.125rem 0.625rem 0.125rem 0.375rem;
  border-radius: 999px;
  font-size: 0.8125rem;
  font-weight: 500;
  white-space: nowrap;
}

.badge-complete,
.badge-plan-approved {
  background: var(--success-surface);
  color: var(--success);
}

.badge-incomplete {
  background: var(--warning-surface);
  color: var(--warning);
  font-weight: 700;
}

.badge-open {
  background: var(--accent);
  color: var(--accent-foreground);
}

.badge-rest_day,
.badge-no_work,
.badge-plan-draft {
  background: var(--neutral-surface);
  color: var(--muted-foreground);
}

.badge-inside {
  background: var(--success-surface);
  color: var(--success);
}

.badge-approaching,
.badge-plan-submitted {
  background: var(--warning-surface);
  color: var(--warning);
}

.badge-over,
.badge-plan-rejected {
  background: var(--danger-surface);
  color: var(--danger);
  font-weight: 700;
}

.badge-cutover {
  background: var(--neutral-surface);
  color: var(--muted-foreground);
}

/* My day's live status pill, distinct from the stored badge-* statuses
   above: working and on a break read as their own colours rather than one
   shared "open". */
.badge-progress-not_started {
  background: var(--neutral-surface);
  color: var(--muted-foreground);
}

.badge-progress-working {
  background: var(--accent);
  color: var(--accent-foreground);
}

.badge-progress-on_break {
  background: var(--info-surface);
  color: var(--info);
}

.badge-progress-done {
  background: var(--success-surface);
  color: var(--success);
}

/* Team today: each state takes an existing pair; the icon and words carry
   the meaning. */
.badge-dashboard-working,
.badge-dashboard-done {
  background: var(--success-surface);
  color: var(--success);
}

.badge-dashboard-on_break {
  background: var(--accent);
  color: var(--accent-foreground);
}

.badge-dashboard-teleworking,
.badge-dashboard-external_work {
  background: var(--info-surface);
  color: var(--info);
}

.badge-dashboard-on_leave {
  background: var(--leave-surface);
  color: var(--leave);
}

/* Not started is ordinary until the person's morning reminder hour; only
   then does it ask for HR's eye. */
.badge-dashboard-not_started.is-late {
  background: var(--warning-surface);
  color: var(--warning);
}

.badge-dashboard-not_started,
.badge-dashboard-absent,
.badge-dashboard-not_working_day {
  background: var(--neutral-surface);
  color: var(--muted-foreground);
}

.search-form {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.75rem;
  margin: 1rem 0 1.25rem;
}

.search-form .field {
  flex: 1 1 12rem;
  margin: 0;
}

/* In a toolbar the search sits at the row's end while the chips leave it
   room, and takes a row of its own, still one line, when they do not. */
.toolbar > .search-form {
  flex: 1 1 22rem;
  max-width: 28rem;
}

/* Chips and the search keep their own margins elsewhere; in a toolbar the
   one gap between them is the cluster's. */
.toolbar > .chips,
.toolbar > .search-form,
.toolbar > .figures {
  margin: 0;
}

.toolbar > .figures {
  flex: 0 1 auto;
  grid-template-columns: repeat(2, minmax(8.5rem, 13rem));
}

/* Console forms: a role's line and its one button, the weekday tick grid,
   and the day a grant would override. */

.role-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1rem;
  padding: 0.75rem 0;
  border-top: 1px solid var(--border);
}

.role-row > p {
  flex: 1 1 12rem;
  margin: 0;
}

.role-row > .field-hint {
  flex-basis: 100%;
  order: 1;
}

.weekday-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(7rem, 1fr));
  gap: 0 0.75rem;
}

.day-now {
  margin-bottom: 1.25rem;
  padding: 1rem 1.25rem 0.25rem;
  background: var(--muted);
  border-left: 4px solid var(--brand);
  border-radius: var(--radius);
}

.day-now h3 {
  margin-bottom: 0.5rem;
}

.day-now .stamps {
  margin: 0;
}

.day-now .stamps > div:last-child {
  border-bottom: 0;
}

/* Month close and archive: the select column's label is for screen
   readers, the person's name sitting in the next cell; 64 hex digits have no
   break, so a hash wraps anywhere. */

.select-cell .check {
  justify-content: center;
  min-height: 1.3125rem;
}

.select-cell .checkbox {
  width: 1.5rem;
  height: 1.5rem;
}

.hash {
  display: inline-block;
  max-width: 17ch;
  font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: 0.75rem;
  white-space: normal;
  word-break: break-all;
  vertical-align: top;
}

.archive-docs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
}

.hash-list {
  white-space: normal;
  margin: 0.5rem 0 0;
  padding-left: 1rem;
  font-size: 0.75rem;
  color: var(--muted-foreground);
}

.hash-list li + li {
  margin-top: 0.375rem;
}

.hash-list .hash {
  display: block;
  max-width: none;
}

summary {
  cursor: pointer;
  padding-block: 0.75rem;
}

/* The stamping screen: one column, the stamp due next as the one wide
   button a thumb reaches. */

.day-head {
  margin-bottom: 1.25rem;
}

.day-head h1 {
  margin-bottom: 0.375rem;
}

.day-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.75rem;
  margin: 0;
  color: var(--muted-foreground);
  font-weight: 500;
}

.offline-note {
  display: none;
}

.offline-note.shown {
  display: flex;
}

.stamp-card {
  border-top: 4px solid var(--brand);
}

.stamps {
  display: grid;
  margin: 0 0 1.25rem;
}

.stamps > div {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  padding: 0.625rem 0;
  border-bottom: 1px solid var(--border);
}

.stamps > div:first-child {
  padding-top: 0;
}

.stamps dt {
  color: var(--muted-foreground);
}

.stamps dd {
  margin: 0;
  font-size: 1.125rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.figures {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.75rem;
  margin: 0 0 1.25rem;
}

/* Tiles stop growing at 13rem, so a wide card shows a row of figures rather
   than four stretched slabs. */
@container (width >= 30rem) {
  .figures {
    grid-template-columns: repeat(auto-fit, minmax(8.5rem, 13rem));
  }
}

/* The number reads first, and every tile's number sits on the same line
   whether or not its label wraps. */
.figures > div {
  display: flex;
  flex-direction: column-reverse;
  justify-content: flex-end;
  gap: 0.125rem;
  padding: 0.75rem 0.875rem;
  background: var(--tile);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  min-width: 0;
}

.figures dt {
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--muted-foreground);
}

.figures dd {
  margin: 0;
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  color: var(--heading);
}

.figures dd > a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin-block: -0.5rem;
}

.projection {
  margin-bottom: 1.25rem;
}

.projection p {
  margin-bottom: 0.25rem;
}

.projection strong {
  font-size: 1.15rem;
}

.projection strong .icon {
  color: var(--brand);
}

/* Not now and the confirmation share one row, so both are in view where the
   stamp button was. */
.stamp-confirm .actions {
  display: flex;
  gap: 0.75rem;
}

.stamp-confirm .actions > * {
  flex: 1;
  min-width: 0;
}

.stamp-confirm .btn-stamp {
  width: 100%;
}

/* Below 360px the two labels no longer fit side by side, so they stack,
   the confirmation under "Not now" as the stamp button was. */
@media (max-width: 22.5rem) {
  .stamp-confirm .actions {
    flex-direction: column;
  }
}

.btn-stamp {
  width: 100%;
  min-height: 68px;
  font-size: 1.25rem;
  font-weight: 700;
  border-radius: 12px;
}

.btn-stamp .icon {
  font-size: 1.5rem;
}

.card-link {
  margin: 1.25rem 0;
}

.card-link a {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  min-height: 44px;
  font-weight: 500;
}

/* An underline under the icon reads as a stray rule; only the words carry
   it. */
.card-link a:has(> .icon) {
  text-decoration: none;
}

.card-link a:has(> .icon) > span:not(.icon) {
  text-decoration: underline;
  text-decoration-thickness: 1px;
}

.notifications-link a {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.875rem 1rem;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--foreground);
  text-decoration: none;
  font-weight: 500;
}

.notifications-link a > span:nth-child(2) {
  flex: 1;
}

.notifications-link a:hover {
  border-color: var(--link);
  color: var(--link);
}

.notifications-link .icon:first-child {
  color: var(--brand);
}

/* A one-line warning, unlike .toast: it names what needs attention without
   claiming an action just happened. */
.notice {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.5rem;
  padding-block: 0.625rem;
  margin-bottom: 1.25rem;
  color: var(--warning);
}

.notice .icon {
  align-self: center;
}

.notice a {
  color: inherit;
  font-weight: 700;
}

.notice > span:not(.icon) {
  flex: 1;
  min-width: 0;
}

/* Inline links in a line of text: the line height gives each a 24px target,
   the WCAG 2.2 minimum, without spreading the lines apart. */
.open-days,
.to-correct {
  line-height: 1.6;
}

.open-days a,
.to-correct a {
  padding-block: 0.125rem;
}

.cutover-note {
  margin-bottom: 1.25rem;
}

.month-nav {
  display: flex;
  justify-content: space-between;
  gap: 0.5rem;
}

.month-nav .btn {
  min-height: 40px;
}

/* Under a person's tabs the month nav leads the record rather than
   spanning it. */
.detail > .month-nav {
  justify-content: flex-start;
  margin-bottom: 1.25rem;
}

.day-list {
  list-style: none;
  padding: 0;
  margin: 0;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
}

.day-list li + li {
  border-top: 1px solid var(--border);
}

.day-row {
  display: grid;
  grid-template-columns: 3.75rem minmax(0, 1fr) auto;
  grid-template-areas:
    "date mode badge"
    "date times worked";
  align-items: center;
  gap: 0.125rem 0.75rem;
  min-height: 44px;
  padding: 0.625rem 1rem;
  color: var(--card-foreground);
  text-decoration: none;
  font-variant-numeric: tabular-nums;
  border-left: 4px solid transparent;
}

.day-row:hover {
  background: var(--row-hover);
  color: var(--card-foreground);
}

.day-row:hover .day-date {
  color: inherit;
}

.day-row-off {
  background: color-mix(in srgb, var(--muted) 45%, transparent);
  color: var(--muted-foreground);
  min-height: 40px;
  padding-block: 0.375rem;
}

.day-row-today {
  border-left-color: var(--brand);
}

.day-date {
  grid-area: date;
  font-weight: 700;
  white-space: nowrap;
}

.day-row-today .day-date {
  color: var(--heading);
}

.day-mode {
  grid-area: mode;
}

/* The usual mode recedes, so a day worked differently reads at a glance. */
.day-mode-usual {
  color: var(--muted-foreground);
}

.day-times {
  grid-area: times;
  font-size: 0.875rem;
  color: var(--muted-foreground);
}

.day-times .seg {
  white-space: nowrap;
}

.day-worked {
  grid-area: worked;
  font-weight: 700;
  text-align: right;
}

.gap {
  color: var(--warning);
  font-weight: 700;
}

.day-status {
  grid-area: badge;
  display: flex;
  align-items: center;
  gap: 0.375rem;
  justify-self: end;
}

/* The chevron says the row is a link without relying on the badge's
   colour, which is absent on a future day. The child combinator keeps it
   off a badge's own icon. */
.day-status > .icon:last-child {
  color: var(--muted-foreground);
}

.time-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
  gap: 0 1rem;
}

/* Mode names ("O meu dia habitual") need a wider select than a time does. */
.time-grid:has(select) {
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
}

.changes {
  list-style: none;
  padding: 0;
  margin: 0;
}

.changes li {
  padding: 0.75rem 0;
  border-bottom: 1px solid var(--border);
}

.changes li:first-child {
  padding-top: 0;
}

.changes li:last-child {
  border-bottom: 0;
  padding-bottom: 0;
}

.request-line {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 0.5rem;
}

.changes p {
  margin: 0 0 0.25rem;
}

.changes form {
  margin-top: 0.25rem;
}

/* Telework attestation: the days waiting, and the flag on a day that is. */

.attest-fieldset {
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}

.attest-fieldset legend {
  margin-bottom: 0.5rem;
  font-weight: 600;
}

.attest-days {
  list-style: none;
  padding: 0;
  margin: 0 0 1rem;
}

.attest-days li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 0 0.75rem;
  padding: 0.25rem 0;
  border-bottom: 1px solid var(--border);
}

.attest-days li:last-child {
  border-bottom: 0;
}

.attest-days li > a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  white-space: nowrap;
}

.table .attest-days {
  margin: 0;
  width: max-content;
}

.attest-flag {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  margin-left: 0.5rem;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--info);
}

p.attest-flag {
  margin-left: 0;
}

/* The plan calendar: a fixed seven-column table whose cells carry the day's
   state as a coloured chip with icon and words. td:empty is a day outside
   the month. */

.cal .table {
  table-layout: fixed;
}

.cal .table th,
.cal .table td {
  padding: 0;
  white-space: normal;
  border-left: 1px solid var(--border);
}

.cal .table th:first-child,
.cal .table td:first-child {
  border-left: 0;
}

.cal .table thead th {
  position: static;
  text-align: center;
  padding: 0.5rem 0.25rem;
}

.cal .table tbody tr:hover {
  background: transparent;
}

.cal .table td:empty {
  background: repeating-linear-gradient(-45deg, transparent 0 6px, color-mix(in srgb, var(--muted) 60%, transparent) 6px 7px);
}

.cal-day {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  min-height: 5.25rem;
  padding: 0.5rem;
}

/* An inert day's number lines up with a button day's, which sits inside
   the cell's 4px padding and the button's 1px border. */
div.cal-day {
  padding: calc(0.5rem + 5px);
}

/* A future working day is a button that fills the request form. Its
   border is what marks it as a control, so it takes the input border
   (4.6:1) rather than --border-strong (1.9:1). */
.cal .table td:has(> button.cal-day) {
  padding: 4px;
}

button.cal-day {
  width: 100%;
  height: 100%;
  min-height: calc(5.25rem - 8px);
  margin: 0;
  border: 1px solid var(--input);
  border-radius: var(--radius-sm);
  font: inherit;
  text-align: left;
  color: inherit;
  background: var(--card);
  cursor: pointer;
}

button.cal-day:hover {
  border-color: var(--link);
  background: color-mix(in srgb, var(--accent) 50%, var(--card));
}

button.cal-day:focus-visible {
  outline: 3px solid var(--ring);
  outline-offset: 1px;
}

.cal-num {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.75rem;
  height: 1.75rem;
  padding: 0 0.375rem;
  border-radius: 999px;
  font-weight: 700;
  font-size: 0.9375rem;
}

.cal-day[aria-current="date"] .cal-num {
  background: var(--brand);
  color: var(--navy-deep);
}

.cal-day[aria-current="date"] {
  box-shadow: inset 0 0 0 2px var(--brand);
}

.cal-state {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.125rem 0.5rem 0.125rem 0.375rem;
  border-radius: var(--radius-sm);
  font-size: 0.75rem;
  font-weight: 500;
  line-height: 1.3;
  background: var(--state-surface, var(--neutral-surface));
  color: var(--state-ink, var(--muted-foreground));
}

.cal-state .icon {
  font-size: 1rem;
}

.cal-legend {
  display: flex;
  list-style: none;
  flex-wrap: wrap;
  gap: 0.375rem 1rem;
  margin: -0.5rem 0 1.25rem;
  padding: 0;
  font-size: 0.8125rem;
}

/* The pull-up tucks the legend under the Plan calendar; after a line of
   text, as on the leave map, it keeps its distance. */
.field-hint + .cal-legend {
  margin-top: 0.75rem;
}

.cal-legend li {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  color: var(--state-ink, var(--muted-foreground));
}

.cal-weekly_rest {
  --state-surface: var(--neutral-surface);
  --state-ink: var(--muted-foreground);
}

.cal-day.cal-weekly_rest {
  background: color-mix(in srgb, var(--muted) 45%, transparent);
}

.cal-public_holiday {
  --state-surface: var(--info-surface);
  --state-ink: var(--info);
}

.cal-annual_leave {
  --state-surface: var(--leave-surface);
  --state-ink: var(--leave);
}

.cal-justified_absence,
.cal-unjustified_absence {
  --state-surface: var(--neutral-surface);
  --state-ink: var(--foreground);
}

.cal-pending {
  --state-surface: var(--warning-surface);
  --state-ink: var(--warning);
}

.cal-approved {
  --state-surface: var(--success-surface);
  --state-ink: var(--success);
}

.cal-rejected {
  --state-surface: var(--danger-surface);
  --state-ink: var(--danger);
}

.cal-day.cal-rejected .cal-state {
  text-decoration: line-through;
}

/* The leave plan: twelve month grids, a tile per working day whose
   checkbox covers the tile. Weekends and holidays are inert cells. */

.leave-year {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(20rem, 100%), 1fr));
  gap: 1rem;
  margin: 1rem 0 1.5rem;
}

.leave-month {
  margin: 0;
  padding: 0.875rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

.leave-past summary {
  cursor: pointer;
  font-family: var(--font-heading);
  font-weight: 600;
  color: var(--heading);
}

.leave-past[open] summary {
  margin-bottom: 0.625rem;
}

.leave-month legend {
  float: left;
  width: 100%;
  margin-bottom: 0.625rem;
  font-family: var(--font-heading);
  font-weight: 600;
  color: var(--heading);
}

.leave-grid {
  clear: both;
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 3px;
}

.leave-wd {
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-align: center;
  color: var(--muted-foreground);
  padding-bottom: 0.125rem;
}

.leave-off,
.leave-blank,
.leave-grid .check {
  aspect-ratio: 1;
  min-height: 0;
  display: grid;
  place-items: center;
  border-radius: var(--radius-sm);
  font-size: 0.875rem;
  font-variant-numeric: tabular-nums;
}

.leave-off {
  color: var(--muted-foreground);
  background: color-mix(in srgb, var(--muted) 55%, transparent);
}

.leave-holiday {
  --state-ink: var(--info);
  position: relative;
  color: var(--info);
  background: var(--info-surface);
}

/* Each cell state carries the glyph its legend entry shows, so a holiday, a
   day already reached and a planned day differ by more than their tint. */
.leave-holiday::after,
.leave-grid .check:has(:checked) label::after,
.leave-grid .check:has(:disabled:not(:checked)) label::after {
  font-family: "Material Symbols Outlined";
  font-size: 0.6875rem;
  line-height: 1;
  position: absolute;
  top: 2px;
  right: 2px;
}

.leave-holiday::after {
  content: "flag";
}

.leave-grid .check:has(:disabled:not(:checked)) label::after {
  content: "history";
}

.leave-grid .check {
  position: relative;
  gap: 0;
  border: 1px solid var(--border-strong);
  background: var(--card);
  font-weight: 500;
  transition: background-color 120ms ease-out, border-color 120ms ease-out;
}

.leave-grid .checkbox {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.leave-grid .check label {
  pointer-events: none;
}

.leave-grid .check:hover {
  border-color: var(--link);
}

.leave-grid .check:has(:focus-visible) {
  outline: 3px solid var(--ring);
  outline-offset: 1px;
}

.leave-grid .check:has(:checked) {
  background: var(--leave-surface);
  border-color: var(--leave);
  color: var(--leave);
  font-weight: 700;
}

.leave-grid .check:has(:checked) label::after {
  content: "check_circle";
}

.leave-grid .check:has(:disabled) {
  border-style: dashed;
  border-color: var(--border);
  color: var(--muted-foreground);
  background: color-mix(in srgb, var(--muted) 35%, transparent);
}

.leave-grid .check:has(:disabled) .checkbox {
  cursor: default;
}

.leave-grid .check:has(:checked:disabled) {
  border-style: solid;
  background: color-mix(in srgb, var(--leave-surface) 60%, transparent);
  color: var(--leave);
}

/* Save draft and Send to HR stay reachable while the year's twelve months
   scroll past; on a phone the bar sits just above the fixed app nav. */
.leave-actionbar {
  position: sticky;
  bottom: 0;
  z-index: 2;
  margin: 1rem -1rem 0;
  padding: 0.75rem 1rem;
  background: var(--card);
  border-top: 1px solid var(--border);
}

/* Phone and tablet held upright: the app nav moves to a fixed bar at the
   bottom, in reach of a thumb, and sign-out shrinks to its icon, keeping its
   name in aria-label. */

@media (max-width: 48rem) {
  :root {
    --nav-height: calc(3.75rem + env(safe-area-inset-bottom));
  }

  /* The room is for the tab bar, which a standalone page does not have. */
  body:not(:has(.standalone)) {
    padding-bottom: var(--nav-height);
  }

  html {
    scroll-padding-bottom: calc(var(--nav-height) + 0.5rem);
  }

  html:has(.leave-actionbar) {
    scroll-padding-bottom: calc(var(--nav-height) + var(--actionbar-height) + 0.5rem);
  }

  .leave-actionbar {
    bottom: var(--nav-height);
  }

  .shell-header {
    flex-wrap: nowrap;
    justify-content: space-between;
    gap: 0.75rem;
    min-height: 3.5rem;
    padding: 0.375rem 1rem;
  }

  .brand img {
    height: 36px;
  }

  .brand span {
    font-size: 1.125rem;
  }

  .shell-nav {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 5;
    flex: none;
    flex-wrap: nowrap;
    justify-content: space-around;
    gap: 0;
    height: var(--nav-height);
    padding: 0.25rem 0.25rem env(safe-area-inset-bottom);
    background: var(--chrome);
    border-top: 1px solid var(--chrome-line);
    box-shadow: 0 -2px 8px rgb(10 25 47 / 0.25);
    overflow-x: auto;
    scrollbar-width: none;
  }

  /* Each link is as wide as its label, so six Portuguese labels fit 320px
     where six equal columns would clip the longest. */
  .shell-nav a {
    flex: 1 1 auto;
    min-width: 0;
    flex-direction: column;
    justify-content: center;
    gap: 0.125rem;
    min-height: 3.25rem;
    padding: 0 0.125rem;
    font-size: 0.75rem;
    letter-spacing: 0;
    text-transform: none;
    font-weight: 500;
    white-space: nowrap;
  }

  .shell-nav a .icon {
    font-size: 1.5rem;
    opacity: 1;
  }

  .shell-nav a {
    position: relative;
  }

  .shell-nav a[aria-current="page"] {
    font-weight: 700;
  }

  /* The phone bar marks the current tab the way the desk header does, at
     its top edge. */
  .shell-nav a[aria-current="page"]::before {
    content: "";
    position: absolute;
    top: 0;
    left: 25%;
    right: 25%;
    height: 3px;
    border-radius: 0 0 3px 3px;
    background: var(--brand);
  }

  .shell-header .btn-signout {
    min-width: 44px;
    min-height: 44px;
    padding: 0.5rem;
  }

  .btn-signout .btn-label {
    display: none;
  }

  main {
    padding-bottom: 2rem;
  }

  .page-head {
    flex-direction: column;
    align-items: stretch;
  }

  .card {
    padding: 1.25rem 1rem;
    border-radius: 12px;
  }

  .lead {
    font-size: 1rem;
  }

  /* The mode takes the row's full width and the badge moves under the
     times, so a long badge never squeezes the mode into a column. The
     chevron keeps a column of its own down the right edge, so it never
     drops to a line of its own. */
  .day-row {
    grid-template-columns: 3.75rem minmax(0, 1fr) auto auto;
    grid-template-areas:
      "date mode mode chevron"
      "date times times chevron"
      "date badge worked chevron";
    gap: 0.25rem 0.5rem;
    padding: 0.625rem 0.5rem 0.625rem 0.75rem;
  }

  .day-status {
    display: contents;
  }

  .day-status > .badge {
    grid-area: badge;
    justify-self: start;
  }

  .day-status > .icon:last-child {
    grid-area: chevron;
  }

  .day-times {
    font-size: 0.8125rem;
  }

  .figures {
    gap: 0.5rem;
  }

  .figures dd {
    font-size: 1.25rem;
  }

  .cal-day {
    min-height: 3.25rem;
    padding: 0.25rem;
    align-items: center;
  }

  .cal-num {
    align-self: center;
    min-width: 1.5rem;
    height: 1.5rem;
    font-size: 0.875rem;
  }

  .cal-state {
    padding: 0.125rem;
    background: transparent;
  }

  .cal-state > span:not(.icon) {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .cal-state .icon {
    font-size: 1.125rem;
  }

  .leave-off,
  .leave-blank,
  .leave-grid .check {
    min-width: 44px;
    min-height: 44px;
  }

  .table caption {
    padding: 0.875rem 1rem 0.5rem;
    font-size: 1.0625rem;
  }

  .tabs {
    margin-inline: calc(var(--gutter) * -1);
    padding-inline: var(--gutter);
  }

  .chips {
    gap: 0.375rem;
  }

  .chips a {
    min-height: 36px;
    padding: 0 0.75rem;
    font-size: 0.875rem;
  }
}

/* On a phone the bar slides away while a field has focus, so the keyboard
   never leaves a strip of navigation over the field being typed in. */
@media (max-width: 48rem) {
  .shell:has(.input:focus, textarea:focus) .shell-nav {
    translate: 0 100%;
    transition: translate 150ms ease-out;
  }

}

/* Between the bar and the desk the header holds six links on one line only
   when they are set tighter and sign-out keeps its icon alone. Up to 54rem
   that is still too wide for super's six, which wrap the header to two rows,
   so there the links drop their icons. */
@media (min-width: 48.0625rem) and (max-width: 54rem) {
  .shell-nav a .icon {
    display: none;
  }
}

@media (min-width: 48.0625rem) and (max-width: 64rem) {
  .shell-nav a {
    padding: 0 0.5rem;
    font-size: 0.75rem;
    letter-spacing: 0.06em;
  }

  .shell-header .btn-signout {
    min-width: 44px;
    padding: 0.5rem;
  }

  .btn-signout .btn-label {
    display: none;
  }
}

/* A phone held sideways is wide and short: the bar would take a third of
   the height, so the app nav stands as a rail on the left, under the
   header, and the header shrinks to one line. */
@media (max-width: 64rem) and (max-height: 30rem) and (orientation: landscape) {
  :root {
    --header-height: 3rem;
  }

  body:has(.shell-app) {
    padding-bottom: 0;
  }

  .shell-header {
    flex-wrap: nowrap;
    justify-content: space-between;
    gap: 0.75rem;
    min-height: var(--header-height);
    padding-block: 0.25rem;
  }

  .brand img {
    height: 32px;
  }

  .brand span {
    font-size: 1.0625rem;
  }

  .shell-app .shell-nav {
    position: fixed;
    top: var(--header-height);
    bottom: 0;
    left: 0;
    right: auto;
    z-index: 5;
    flex: none;
    flex-direction: column;
    flex-wrap: nowrap;
    justify-content: flex-start;
    gap: 0.25rem;
    width: calc(var(--rail) + env(safe-area-inset-left));
    height: auto;
    padding: 0.5rem 0.25rem 0.5rem calc(0.25rem + env(safe-area-inset-left));
    background: var(--chrome);
    border-top: 0;
    border-right: 1px solid var(--chrome-line);
    box-shadow: 2px 0 8px rgb(10 25 47 / 0.25);
    overflow-y: auto;
    scrollbar-width: none;
  }

  .shell-app .shell-nav a {
    flex: none;
    flex-direction: column;
    justify-content: center;
    gap: 0.125rem;
    min-height: 3.25rem;
    padding: 0 0.125rem;
    font-size: 0.75rem;
    letter-spacing: 0;
    text-transform: none;
    font-weight: 500;
    white-space: nowrap;
  }

  .shell-app .shell-nav a .icon {
    font-size: 1.5rem;
    opacity: 1;
  }

  .shell-app main {
    padding-left: calc(var(--rail) + env(safe-area-inset-left) + var(--gutter));
  }

  .shell-app .shell-footer {
    padding-left: calc(var(--rail) + env(safe-area-inset-left) + 1.5rem);
  }

  .shell-header .btn-signout {
    min-width: 44px;
    min-height: 44px;
    padding: 0.5rem;
  }

  .btn-signout .btn-label {
    display: none;
  }

  main {
    padding-bottom: 1.5rem;
  }
}

/* Desk: the console sections stand as a sidebar beside the page. The
   disclosure stays in the markup so a phone can fold it; here its summary
   hides and its content is shown whether or not it is open. */

@media (min-width: 64rem) {
  main:has(> .console-nav) {
    display: grid;
    grid-template-columns: 13rem minmax(0, 1fr);
    column-gap: var(--gutter);
    align-items: start;
  }

  .console-nav {
    position: sticky;
    top: calc(var(--header-height) + var(--gap));
    max-height: calc(100dvh - var(--header-height) - var(--gap) * 2);
    overflow-y: auto;
    margin: 0;
    padding: 0.25rem;
  }

  .console-menu > summary {
    display: none;
  }

  .console-menu::details-content {
    content-visibility: visible;
  }

  .console-groups {
    margin: 0;
    padding: 0;
    background: transparent;
    border: 0;
    box-shadow: none;
    gap: 0.5rem;
  }
}

/* With a mouse the sidebar's sixteen links fit a 900px-tall screen at 36px
   each, well over the 24px target minimum; at 44px the last group scrolled
   out of sight. */
@media (min-width: 64rem) and (pointer: fine) {
  .console-group > a {
    min-height: 36px;
    padding-block: 0.25rem;
  }
}

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

/* Print: HR files the month list and a person's record. Chrome, navigation
   and actions go; tables and cards keep their rules in black on white. */

@media print {
  :root {
    color-scheme: light;
  }

  body {
    background: #fff;
    color: #000;
    padding: 0;
  }

  .shell-header,
  .shell-footer,
  .shell-nav,
  .skip-link,
  .console-nav,
  .list-pane,
  .month-nav,
  .actions,
  .btn,
  .card-link,
  .notifications-link,
  .toast,
  form {
    display: none !important;
  }

  main {
    max-width: none;
    padding: 0;
  }

  .panes {
    display: block;
  }

  .card,
  .table-wrap,
  .day-list {
    background: #fff;
    box-shadow: none;
    border-color: #999;
    break-inside: avoid;
  }

  .table-wrap {
    overflow: visible;
  }

  .table thead th {
    position: static;
  }

  a {
    color: inherit;
    text-decoration: none;
  }
}

/* Disclosures take the menus' chevron, right of the summary, so an open and
   a closed one look different. The empty alt text keeps the icon's name out
   of what a screen reader says. */
details:not(.account-menu, .console-menu) > summary {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  list-style: none;
  cursor: pointer;
}

details:not(.account-menu, .console-menu) > summary::-webkit-details-marker {
  display: none;
}

details:not(.account-menu, .console-menu) > summary::after {
  content: "expand_more" / "";
  font-family: "Material Symbols Outlined";
  font-feature-settings: "liga";
  font-size: 1.25rem;
  line-height: 1;
  color: var(--muted-foreground);
  transition: transform 150ms ease-out;
}

details[open]:not(.account-menu, .console-menu) > summary::after {
  transform: rotate(180deg);
}

.leave-month > summary::after {
  margin-left: auto;
}

/* Two panes holding a table stack until the table fits beside the side card,
   so a row's actions never scroll out of sight; stacked, they follow source
   order. */
@container page (width >= 56rem) and (width < 84rem) {
  .panes:has(.table-wrap),
  .panes:has(.table-wrap):has(> .pane-main:first-child) {
    grid-template-columns: minmax(0, 1fr);
  }

  .panes:has(.table-wrap) > .pane-aside {
    max-width: 40rem;
  }

  .panes:has(.table-wrap) > .pane-aside.pinned {
    position: static;
  }
}

/* The footer reaches the bottom of a short page: the shell's flex only takes
   effect once #root, between body and .shell, is a flex column too. */
#root {
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
}

/* A stamp not yet recorded recedes; a recorded time stays bold. */
.stamps dd.is-empty,
span.is-empty {
  color: var(--muted-foreground);
  font-weight: 400;
}

@media (max-width: 48rem) {
  button.cal-day {
    min-height: calc(3.25rem - 8px);
  }
}

/* The team's two tables share their first four columns, so a fixed layout
   with the same widths lines them up one above the other. */
@container page (width >= 56rem) {
  .team-tables .table {
    table-layout: fixed;
  }

  .team-tables .table th:nth-child(1) {
    width: 26%;
  }

  .team-tables .table th:nth-child(2) {
    width: 30%;
  }

  .team-tables .table th:nth-child(3) {
    width: 16%;
  }

  .team-tables .table th:nth-child(4):not(:last-child) {
    width: 14%;
  }

  .team-tables .table td {
    overflow-wrap: anywhere;
  }
}
