/*
 * Ported verbatim from the IDE's src/App.css (with the token set from
 * src/theme/tokens.css in styles.css), so the mock window and the lens
 * rail on the landing page are the real chrome, not an impression of it.
 * Sections are marked with the App.css line they came from.
 */

/* ---------- Motion primitives (App.css:95) ---------- */
 * mousedown, then a springy release. Colors flip fast and linear-ish; only
 * transforms get the overshoot so nothing flashes past a color stop.
 */
.icon-button,
.activity-bar-item,
.panel-tab,
.button-primary,
.button-subtle,
.output-channel,
.tab-close,
.search-toggle,
.search-chip,
.search-mode-option,
.dialog-button,
.island-compact,
.island-chip,
.island-alert-action,
.island-alert-close,
.menu-bar-item,
.terminal-tab,
.window-control,
.debug-toolbar-button,
.debug-config-picker,
.debug-section-header {
  transition:
    transform var(--duration-bouncy) var(--ease-bouncy),
    background-color var(--duration-fast) var(--ease-out),
    color var(--duration-fast) var(--ease-out),
    opacity var(--duration-fast) var(--ease-out),
    box-shadow var(--duration-normal) var(--ease-out);
}
.icon-button:active,
.activity-bar-item:active,
.panel-tab:active,
.button-primary:active,
.button-subtle:active,
.output-channel:active,
.tab-close:active,
.search-toggle:active,
.search-chip:active,
.search-mode-option:active,
.dialog-button:active,
.island-chip:active,
.island-alert-action:active,
.island-alert-close:active,
.menu-bar-item:active,
.terminal-tab:active,
.debug-toolbar-button:active {
  transform: scale(0.92);
  transition-duration: 60ms;
  transition-timing-function: ease-out;
}

/* ---------- Lens light (App.css:211) ---------- */
/*
 * Lens light. The lit element reads as a slab of glass under a single
 * light: ::before is a 1.5px rim (masked to a ring) with a specular core
 * at the light position, a cool prismatic fringe around it, and a dimmer,
 * warm refracted rim diametrically opposite; ::after is the light bleeding
 * softly into the glass just inside the lit edge. The rim fades into the
 * ordinary border where the light doesn't reach — nothing glows all round.
 * Set `--lens-on: 1` to light it; lensLight.ts moves the light position.
 */
.glass-lens {
  position: relative;
  isolation: isolate;
  --lens-on: 0;
}
.glass-lens::before,
.glass-lens::after {
  content: "";
  position: absolute;
  border-radius: inherit;
  pointer-events: none;
  z-index: -1;
  opacity: calc(var(--lens-on) * var(--glow-strength));
  /* The light position eases here (not on the host) so the host keeps its own transitions. */
  transition:
    opacity var(--duration-spring) var(--ease-out),
    --lens-x var(--duration-normal) var(--ease-out),
    --lens-y var(--duration-normal) var(--ease-out);
}
.glass-lens::before {
  inset: -1px;
  padding: 1.5px;
  -webkit-mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  mask-composite: exclude;
  background:
    radial-gradient(
      45% 120% at var(--lens-x) var(--lens-y),
      rgb(var(--lens-core) / 0.95),
      rgb(var(--lens-core) / 0.55) 18%,
      rgb(var(--lens-core) / 0.12) 55%,
      transparent 100%
    ),
    radial-gradient(
      60% 150% at var(--lens-x) var(--lens-y),
      rgb(var(--lens-cool) / 0.6),
      rgb(var(--lens-cool) / 0.35) 40%,
      transparent 100%
    ),
    radial-gradient(
      40% 110% at calc(100% - var(--lens-x)) calc(100% - var(--lens-y)),
      rgb(var(--lens-core) / 0.4),
      rgb(var(--lens-warm) / 0.4) 30%,
      rgb(var(--lens-warm) / 0.1) 70%,
      transparent 100%
    );
}
.glass-lens::after {
  inset: 0;
  background:
    radial-gradient(
      60% 100% at var(--lens-x) var(--lens-y),
      rgb(var(--lens-bleed) / 0.11),
      rgb(var(--lens-cool) / 0.04) 45%,
      transparent 75%
    ),
    radial-gradient(
      45% 80% at calc(100% - var(--lens-x)) calc(100% - var(--lens-y)),
      rgb(var(--lens-warm) / 0.05),
      transparent 70%
    );
}
.glass-lens.is-active,
.glass-lens:focus-visible {
  --lens-on: 1;
}
.glass-lens:focus-visible {
  outline: none;
}
/* Momentary lens for triggers with no lasting active state (e.g. Settings):
   lit only while pressed — fast in, then the usual spring fade on release. */
.glass-lens.lens-on-press:active {
  --lens-on: 1;
}
.glass-lens.lens-on-press:active::before,
.glass-lens.lens-on-press:active::after {
  transition-duration: var(--duration-fast), var(--duration-normal), var(--duration-normal);
}


/* ---------- Workbench layout (App.css:408) ---------- */
.workbench {
  width: 100vw;
  height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--bg-app);
}

.workbench-body {
  flex: 1;
  display: flex;
  min-height: 0;
}

.main-column {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
}

.editor-area {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  background: var(--bg-chrome);
}


/* ---------- Editor card & separators (App.css:439) ---------- */
/*
 * The editor is the one lit surface, set into the chrome as a card whose
 * hairline outline is where the separators live: the line to the sidebar,
 * to the tab bar above and to the panel below are its edges, so they meet
 * in rounded corners instead of crossing. It sits flush with the window's
 * right edge, so only the left corners are rounded; with the tab bar
 * hidden it hangs from the title bar's line instead (square top corner).
 * Overflow is clipped to the corners; Monaco's widgets escape it because
 * the editors are created with fixedOverflowWidgets.
 */
.editor-pane-container {
  flex: 1;
  position: relative;
  min-height: 0;
  display: flex;
  flex-direction: column;
  background: var(--bg-editor);
  border: 1px solid var(--separator);
  border-right: 0;
  border-radius: var(--pane-radius) 0 0 var(--pane-radius);
  overflow: hidden;
}
.tab-bar-slot[data-hidden] + .editor-pane-container {
  border-top-color: transparent;
  border-top-left-radius: 0;
}

.editor-pane-host {
  flex: 1;
  position: relative;
  min-height: 0;
}

/* ---------- Separators & resize handles ---------- */

/*
 * The visible separators are the editor card's outline (see
 * .editor-pane-container). A resize handle is a 1px hit target laid over
 * the card's edge; it draws nothing at rest and grows a rounded pill,
 * stopping --separator-inset short of either end, on hover and while
 * dragging.
 */
:root {
  --pane-radius: var(--radius-lg);
  --separator-inset: 8px;
  --separator-hover-width: 4px;
}
.resize-handle {
  position: relative;
  flex-shrink: 0;
  z-index: 5;
}
.resize-handle::after {
  content: "";
  position: absolute;
  border-radius: var(--radius-pill);
  background: var(--fg);
  opacity: 0;
  transform: scale(0.4);
  transition:
    opacity var(--duration-normal) var(--ease-out) 100ms,
    transform var(--duration-spring) var(--ease-spring) 100ms;
}
.resize-handle:hover::after,
.is-resizing .resize-handle::after {
  opacity: 0.35;
  transform: scale(1);
}
.resize-handle-vertical {
  width: 1px;
  cursor: col-resize;
}
.resize-handle-vertical::after {
  top: var(--separator-inset);
  bottom: var(--separator-inset);
  left: calc((var(--separator-hover-width) - 1px) / -2);
  width: var(--separator-hover-width);
}
.resize-handle-horizontal {
  height: 1px;
  cursor: row-resize;
}
.resize-handle-horizontal::after {
  left: var(--separator-inset);
  right: var(--separator-inset);
  top: calc((var(--separator-hover-width) - 1px) / -2);
  height: var(--separator-hover-width);
}


/* ---------- Activity bar & travelling lens (App.css:528) ---------- */

.activity-bar {
  width: var(--activity-bar-width);
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: center;
  padding: 10px 0;
  background: var(--bg-chrome);
}

.activity-bar-group {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.activity-bar-item {
  width: 34px;
  height: 34px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 11px;
  color: var(--fg-muted);
}
.activity-bar-item:hover {
  background: var(--bg-hover);
  color: var(--fg);
}
.activity-bar-item.active {
  color: var(--fg);
}
/* The active-view highlight is the travelling lens (below), sized to the icons here. */
.activity-lens {
  left: 0;
  width: 34px;
  border-radius: 11px;
}

/*
 * Travelling lens (lensTravel.ts): one lit lens under a rail of icons that
 * travels to whichever is pressed — its top and bottom edges are animated
 * separately, so it stretches into a droplet and snaps in. It fades in place
 * when the rail lights up or goes dark, and squashes with the icon it sits
 * under while that icon is pressed. The rail gives it a left, width and
 * radius; the group it sits in is positioned.
 */
.travel-lens {
  position: absolute;
  background: var(--bg-active);
  pointer-events: none;
  transition:
    opacity var(--duration-spring) var(--ease-out),
    scale var(--duration-bouncy) var(--ease-bouncy);
}
.travel-lens.is-off {
  opacity: 0;
}
:has(> .travel-stop.active:active) > .travel-lens {
  scale: 0.92;
  transition-duration: var(--duration-spring), 60ms;
  transition-timing-function: var(--ease-out), ease-out;
}
/* The lens underneath is the active background; a hover tint on top would double it. */
.travel-stop.active:hover {
  background: transparent;
}
.travel-stop svg {
  transition: transform var(--duration-bouncy) var(--ease-bouncy);
}
.travel-stop.active svg {
  transform: scale(1.06);
}
/* The glyph the lens lands on: held still until the glass reaches it, then squashed and popped. */
.travel-stop.is-landing svg {
  animation: lens-land var(--duration-bouncy) both;
  animation-delay: var(--land-delay, 0ms);
}
@keyframes lens-land {
  from {
    transform: scale(1);
    animation-timing-function: var(--ease-out);
  }
  30% {
    transform: scale(0.86);
    animation-timing-function: var(--ease-bouncy);
  }
  to {
    transform: scale(1.06);
  }
}
/* A glyph the lens sweeps past on its way: lit for a moment as the glass crosses it. */
.travel-stop.is-passed {
  animation: lens-pass calc(var(--duration-normal) * 1.5) var(--ease-out) both;
  animation-delay: var(--pass-delay, 0ms);
}
.travel-stop.is-passed svg {
  animation: lens-pass-glyph calc(var(--duration-normal) * 1.5) var(--ease-out) both;
  animation-delay: var(--pass-delay, 0ms);
}
@keyframes lens-pass {
  35% {
    color: var(--fg);
  }
}
@keyframes lens-pass-glyph {
  35% {
    transform: scale(1.05);
  }
}

/* ---------- Sidebar ---------- */


/* ---------- Sidebar & explorer (App.css:645) ---------- */
.sidebar {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  min-width: 0;
  background: var(--bg-sidebar);
  animation: spring-in-left var(--duration-spring) var(--ease-spring) both;
}
.sidebar-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  height: 30px;
  padding: 4px 10px 0 16px;
}

.sidebar-section-title {
  min-width: 0;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--fg-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.file-tree {
  padding: 0 8px 12px;
  outline: none;
  min-height: 100%;
}
.file-tree-filler {
  height: 24px;
}

.tree-status {
  padding: 8px 16px;
  color: var(--fg-muted);
}

.tree-row {
  display: flex;
  align-items: center;
  gap: 5px;
  height: 25px;
  padding-right: 8px;
  border-radius: var(--radius-sm);
  white-space: nowrap;
  color: var(--fg-secondary);
  font-size: 12.5px;
  transition:
    background-color var(--duration-fast) var(--ease-out),
    color var(--duration-fast) var(--ease-out);
}
.tree-row:hover {
  background: var(--bg-hover);
  color: var(--fg);
}
.tree-row.selected {
  background: var(--bg-hover);
}
.tree-row.active {
  background: var(--bg-selected);
  color: var(--fg);
}
.file-tree:focus-visible .tree-row.selected {
  box-shadow: inset 0 0 0 1px var(--border-strong);
}

.tree-chevron {
  display: inline-flex;
  width: 14px;
  height: 14px;
  align-items: center;
  justify-content: center;
  color: var(--fg-muted);
  transition: transform var(--duration-bouncy) var(--ease-bouncy);
  flex-shrink: 0;
}
.tree-chevron.expanded {
  transform: rotate(90deg);
}
.tree-chevron.hidden {
  visibility: hidden;
}

.tree-label {
  overflow: hidden;
  text-overflow: ellipsis;
}

.file-icon {
  display: block;
  flex-shrink: 0;
  object-fit: contain;
  pointer-events: none;
  /* The pack's glyphs are single-colour silhouettes; flatten them to white. */
  filter: brightness(0) invert(1);
}


/* ---------- Tabs (App.css:920) ---------- */
.tab-bar-slot {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  flex-shrink: 0;
  overflow: clip;
  background: var(--bg-chrome);
}

.tab-bar {
  box-sizing: border-box;
  display: flex;
  align-items: stretch;
  gap: 4px;
  height: var(--tab-bar-height);
  padding: 4px 6px;
  flex-shrink: 0;
  overflow-x: auto;
  overflow-y: hidden;
  background: var(--bg-chrome);
  scrollbar-width: none;
  transition: opacity var(--duration-fast) var(--ease-out);
}
.tab-bar::-webkit-scrollbar {
  display: none;
}
.tab-bar-slot[data-hidden] .tab-bar {
  opacity: 0;
}

/* Each tab is a rounded chip floating in the bar; the active one is the lit surface. */
.tab {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0 4px 0 10px;
  min-width: 0;
  max-width: 220px;
  border-radius: var(--radius-md);
  color: var(--fg-muted);
  position: relative;
  flex-shrink: 0;
  transition:
    color var(--duration-fast) var(--ease-out),
    background-color var(--duration-fast) var(--ease-out);
}
.tab:hover {
  color: var(--fg-secondary);
  background: var(--bg-hover);
}
.tab.active {
  color: var(--fg);
  background: var(--bg-active);
}

.tab-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 12.5px;
}
.tab.dirty .tab-label,
.tab.preview .tab-label {
  font-style: italic;
}
.tab-label-suffix {
  color: var(--fg-muted);
  font-size: 11px;
}

.tab-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 5px;
  color: var(--fg-muted);
  flex-shrink: 0;
}
.tab-close:hover {
  background: var(--bg-active);
  color: var(--fg);
}
.tab-close-x,
.tab-close-dot {
  display: inline-flex;
}
.tab-close-x {
  opacity: 0;
  transform: scale(0.6);
  transition:
    opacity var(--duration-fast) var(--ease-out),
    transform var(--duration-bouncy) var(--ease-bouncy);
}
.tab-close-dot {
  display: none;
  color: var(--fg-secondary);
}
.tab:hover .tab-close-x,
.tab.active .tab-close-x {
  opacity: 1;
  transform: scale(1);
}
.tab.dirty .tab-close-dot {
  display: inline-flex;
}
.tab.dirty .tab-close-x {
  display: none;
}
.tab.dirty .tab-close:hover .tab-close-dot {
  display: none;
}

/* ---------- Breadcrumbs (App.css:1481) ---------- */
.breadcrumbs {
  display: flex;
  align-items: center;
  height: 24px;
  padding: 0 10px;
  flex-shrink: 0;
  font-size: 11.5px;
  color: var(--fg-muted);
  background: var(--bg-editor);
  border-bottom: 1px solid var(--separator);
  overflow: hidden;
  white-space: nowrap;
}
.crumb-group {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
}
.crumb-sep {
  margin: 0 2px;
  color: var(--fg-subtle);
}
.crumb {
  padding: 2px 5px;
  border-radius: 4px;
  color: inherit;
  transition:
    background-color var(--duration-fast) var(--ease-out),
    color var(--duration-fast) var(--ease-out);
}
.crumb-file,
.crumb-symbol {
  color: var(--fg-secondary);
}
.crumb-symbol:hover {
  background: var(--bg-hover);
  color: var(--fg);
}

/* ---------- Title bar, menu bar, window controls (App.css:2455) ---------- */
@keyframes spring-in-left {
  from {
    opacity: 0;
    transform: translateX(-14px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

.title-bar {
  height: var(--title-bar-height);
  flex-shrink: 0;
  display: flex;
  align-items: center;
  background: var(--bg-chrome);
  border-bottom: 1px solid var(--separator);
  user-select: none;
  -webkit-app-region: drag;
}
.title-bar-mac {
  /* Leave room for the traffic lights inset by the Overlay title bar style. */
  padding-left: 78px;
}
.title-bar-brand {
  display: flex;
  align-items: center;
  padding: 0 10px 0 12px;
}
.title-bar-logo {
  /* logo.svg inverted for the black chrome: white tile, glyph in currentColor.
     The radius keeps the file's 308/1400 corner ratio at 20px. */
  width: 20px;
  height: 20px;
  display: grid;
  place-items: center;
  border-radius: 4.5px;
  background: var(--bg-inverse);
  color: var(--fg-inverse);
  -webkit-app-region: no-drag;
  transition: transform var(--duration-fast) var(--ease-out);
}
.title-bar-logo:active {
  transform: scale(0.92);
}
.title-bar-title {
  flex: 1;
  text-align: center;
  font-size: 12.5px;
  color: var(--fg-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding: 0 12px;
}
.title-bar-mac .title-bar-title {
  /* Balance the traffic-light inset so the title is visually centred. */
  padding-right: 78px;
}

/* Clicking the logo collapses the bar: the grid track shrinks to 0fr while
   the items fade and slide toward the logo, so the title stretch reclaims
   the width smoothly instead of snapping. */
.menu-bar {
  display: grid;
  grid-template-columns: 1fr;
  -webkit-app-region: no-drag;
  transition: grid-template-columns var(--duration-normal) var(--ease-out);
}
.menu-bar-items {
  display: flex;
  gap: 1px;
  min-width: 0;
  overflow: hidden;
  transition:
    opacity var(--duration-normal) var(--ease-out),
    transform var(--duration-normal) var(--ease-out),
    visibility 0s linear 0s;
}
.menu-bar-hidden {
  grid-template-columns: 0fr;
  pointer-events: none;
}
.menu-bar-hidden .menu-bar-items {
  opacity: 0;
  transform: translateX(-8px);
  visibility: hidden;
  transition-delay: 0s, 0s, var(--duration-normal);
}
.menu-bar-item {
  padding: 4px 9px;
  border-radius: var(--radius-sm);
  font-size: 12.5px;
  color: var(--fg-secondary);
}
.menu-bar-item:hover,
.menu-bar-item.open {
  background: var(--bg-hover);
  color: var(--fg);
}

.window-controls {
  display: flex;
  height: 100%;
  -webkit-app-region: no-drag;
}
.window-control {
  width: 46px;
  height: 100%;
  display: grid;
  place-items: center;
  color: var(--fg-secondary);
}
.window-control:hover {
  background: var(--bg-hover);
  color: var(--fg);
}
.window-control-close:hover {
  background: var(--danger);
  color: #fff;
}

/* ---------- Dynamic Island (App.css:2593) ---------- */

/*
 * A black pill in the title bar's bezel, reshaping around what's going on
 * (DynamicIsland.tsx says what it shows), and a row of smaller islands
 * beside it — the cursor position, problems, branch, live watchers — each
 * a pill of its own, like the second lobe of the iPhone's island. When the
 * shell opens (or an alert takes it) the lobes slide in and fuse with it;
 * when it closes they pinch off again, one after another.
 *
 * The geometry is driven by registered custom properties the component
 * measures from the content. On the root, the shell's size and where the
 * row of lobes hangs off it; on each lobe its width, how far it is split
 * off (0 tucked inside the link before it, 1 out in the row), and how far
 * it is born (0 a drop still inside its neighbour, 1 a pill of its own).
 * Only those animate — the first two with the spring, so a change
 * overshoots a touch and settles; birth with the drop curves in
 * tokens.css, driven from the component — and every box, radius and
 * offset derives from them, so the whole thing moves as one.
 *
 * Two layers share that geometry. Underneath, the blob layer: the black
 * shapes, painted through a gooey alpha filter so a lobe pulling away from
 * the shell stretches a neck of black and snaps free, and melts back in
 * the same way. On top, the content layer, unfiltered so the text stays
 * crisp; it carries the rim, the shadow and the lens light.
 *
 * Both sit on the stage, a generous canvas centred on the anchor (filters
 * need a real box to work in).
 */
@property --main-w {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}
@property --main-h {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}
@property --row-x {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}
@property --lobe-w {
  syntax: "<length>";
  inherits: false;
  initial-value: 0px;
}
@property --split {
  syntax: "<number>";
  inherits: true;
  initial-value: 0;
}
@property --birth {
  syntax: "<number>";
  inherits: true;
  initial-value: 0;
}

.island {
  position: fixed;
  top: var(--island-top);
  left: 50%;
  width: 0;
  height: 0;
  z-index: 900;
  --stage-x: 600px;
  --stage-y: 60px;
  --island-radius: min(calc(var(--main-h) / 2), 22px);
  /* Space between the shell and the first lobe, and between lobes. */
  --lobe-gap: 8px;
  transition:
    --main-w var(--duration-spring) var(--ease-spring),
    --main-h var(--duration-spring) var(--ease-spring),
    --row-x var(--duration-spring) var(--ease-spring);
  font-size: 12px;
  color: var(--fg);
  -webkit-app-region: no-drag;
}
.island-defs {
  position: absolute;
}

/*
 * The stage: the anchor sits at (--stage-x, --stage-y) inside it. Each
 * layer says where the anchor is in its own box with --ox/--oy. Clicks
 * fall through to the title bar except on the shell.
 */
.island-stage {
  position: absolute;
  left: calc(-1 * var(--stage-x));
  top: calc(-1 * var(--stage-y));
  width: 1200px;
  height: 420px;
  --ox: var(--stage-x);
  --oy: var(--stage-y);
  pointer-events: none;
}

/*
 * Blob layer. The filter re-rasterises this whole box every frame the
 * shapes move, so it is only as big as they are — the shell, centred, and
 * the rows of lobes either side (--row-w, --row-wl, measured) — plus room
 * for the blur, the rim and the shadow.
 */
.island-goo {
  position: absolute;
  --goo-pad: 40px;
  --ox: calc(max(var(--main-w) / 2, var(--row-x) + var(--row-wl, 0px)) + var(--goo-pad));
  --oy: var(--goo-pad);
  left: calc(var(--stage-x) - var(--ox));
  top: calc(var(--stage-y) - var(--oy));
  width: calc(var(--ox) + max(var(--main-w) / 2, var(--row-x) + var(--row-w, 0px)) + var(--goo-pad));
  height: calc(var(--main-h) + 2 * var(--goo-pad));
  filter: url(#island-goo);
}
.island-blob {
  position: absolute;
  background: var(--island-bg);
}
.island-blob-main {
  left: var(--ox);
  top: var(--oy);
  width: var(--main-w);
  height: var(--main-h);
  translate: -50% 0;
  border-radius: var(--island-radius);
}

/*
 * The row of lobes is a chain, the same on both layers: it hangs off the
 * compact shell's right edge (--row-x, from the centre line), and each
 * link sits inside the one before it, placed off that link's right edge.
 * Split, a link stands a gap beyond its predecessor; tucked, its right end
 * is 14px inside the predecessor's, hidden in the same rounded end. So
 * gathering telescopes the row into the shell from the far end, unfurling
 * pops each lobe out of the last, and a link with no width carries the
 * rest of the chain over with it.
 *
 * A link's width and gap are its measured width and the row's gap scaled
 * by --birth, so a lobe that is not there takes no room, and one being
 * born opens up its room as it comes. The link's box is what the chain
 * hangs off; what is painted is the drop, below.
 *
 * Everything that moves — the row's --row-x, each link's --at, the drop's
 * --drop-x — moves by a translate, and the layout offsets underneath are
 * whole pixels. The readout is scaled, and Chromium rounds an element's
 * offset to whole pixels where a transform other than a translation
 * begins; had the fractional motion been in the layout, the text would
 * step a pixel at a time as the row settles. A translate is exact.
 */
.island-row {
  position: absolute;
  left: var(--ox);
  top: var(--oy);
  width: 0;
  height: var(--island-height);
  translate: var(--row-x) 0;
}
.island-lobe {
  --split: 0;
  --birth: 0;
  --w: calc(var(--lobe-w) * var(--birth));
  --gap: calc(var(--lobe-gap) * var(--birth));
  /* Where the box starts, from the end of the link before it. */
  --at: calc(-1 * var(--w) - 14px + var(--split) * (var(--w) + 14px + var(--gap)));
  /*
   * The drop, relative to the box. At birth it is the disc inscribed in
   * the neighbour's rounded end — the same black, so nothing shows — and
   * it slides out and widens into the box as --birth rises; leaving, it
   * shrinks back into that disc. --flow is a bump in either journey:
   * nothing at rest, full at mid-flight, below zero on overshoot.
   */
  --drop-x: calc((1 - var(--birth)) * -1 * (var(--island-height) + var(--gap)));
  --drop-w: calc(var(--island-height) * (1 - var(--birth)) + var(--w));
  --flow: calc(var(--split) * (1 - var(--split)) * 4 + var(--birth) * (1 - var(--birth)) * 4);
  position: absolute;
  left: 100%;
  top: 0;
  width: var(--w);
  height: var(--island-height);
  border-radius: calc(var(--island-height) / 2);
  translate: var(--at) 0;
  transition:
    --split var(--duration-spring) var(--ease-spring) var(--gather, 0s),
    --lobe-w var(--duration-spring) var(--ease-spring);
}
.island.is-split .island-lobe {
  --split: 1;
  transition-delay: var(--unfurl, 0s), 0s;
}
/*
 * --birth itself is animated from the component (BirthDrive in
 * DynamicIsland.tsx) with --ease-birth and --ease-drown, so a lobe that
 * turns round mid-way can retrace its path.
 *
 * The blob layer paints two shapes per link, both pseudo-elements so the
 * link's own box, which the next link hangs off, stays exact. The drop:
 * the lobe's black, thinned a little in flight. And the neck: a bar from
 * the neighbour's end to the drop's near edge, as tall as the drop while
 * they overlap and thinning to nothing as the drop arrives; the goo turns
 * it into the strand of liquid between two bodies, which snaps once it is
 * too thin to survive the blur.
 */
.island-lobe-blob::before {
  content: "";
  position: absolute;
  top: calc(var(--flow) * 2.5px);
  bottom: calc(var(--flow) * 2.5px);
  left: var(--drop-x);
  width: var(--drop-w);
  border-radius: inherit;
  background: var(--island-bg);
}
.island-lobe-blob::after {
  content: "";
  position: absolute;
  left: calc(-1 * var(--at));
  width: max(0px, calc(var(--at) + var(--drop-x)));
  top: 50%;
  height: min(var(--island-height), max(0px, calc(var(--island-height) * 2 * (1 - var(--split) * var(--birth)))));
  translate: 0 -50%;
  border-radius: inherit;
  background: var(--island-bg);
}

/*
 * The left row is the same chain in a mirror: it hangs off the shell's
 * left end, each link stands off its predecessor's left end, the drop
 * slides out leftwards, and the neck runs back from the predecessor's end
 * to the drop's near edge. The same properties drive it; only the sides
 * are swapped, so a lobe is born and sinks here exactly as it does on the
 * right.
 */
.island-row.is-left {
  translate: calc(-1 * var(--row-x)) 0;
}
.island-row.is-left .island-lobe {
  left: auto;
  right: 100%;
  translate: calc(-1 * var(--at)) 0;
}
.island-row.is-left .island-lobe-blob::before {
  left: auto;
  right: var(--drop-x);
}
.island-row.is-left .island-lobe-blob::after {
  left: auto;
  right: calc(-1 * var(--at));
}

/*
 * Content layer: no rim or shadow of its own — the goo filter draws those
 * from the blob layer. The shell is centred by layout, not by a translate:
 * the face inside is centred with left: 50% + translate: -50%, and Chromium
 * rounds an element's offset to whole pixels where a transform begins. With
 * the shell's -w/2 and the face's +w/2 both in layout they cancel exactly
 * and the face's offset is a constant; across a transform the rounding
 * would fall on w/2 alone, and the text would hop half a pixel each time
 * the settling width crossed one.
 */
.island-main {
  position: absolute;
  left: calc(var(--ox) - var(--main-w) / 2);
  top: var(--oy);
  width: var(--main-w);
  height: var(--main-h);
  border-radius: var(--island-radius);
  pointer-events: auto;
}
/* Readouts, not controls: the title bar's drag passes through them. */
.island-lobe-body {
  pointer-events: none;
}
/*
 * The lobe's readout, clipped to the drop so the text rides it (the drop
 * thins a little in flight, but the text never reaches those edges, so
 * the clip keeps the full height and the readout a whole-pixel offset).
 * It only comes up once the drop has mostly left its neighbour (and goes
 * as it sinks back), so the neck is bare black. The next link is a sibling
 * of this box, not a child, so what fades or clips here leaves the rest of
 * the chain alone.
 */
.island-lobe-clip {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: var(--drop-w);
  translate: var(--drop-x) 0;
  display: flex;
  align-items: center;
  overflow: hidden;
  border-radius: inherit;
  opacity: calc(var(--split) * var(--birth) * var(--birth) * var(--birth));
}
.island-lobe-face {
  flex: none;
  display: flex;
  align-items: center;
  width: max-content;
  height: var(--island-height);
  padding: 0 11px;
  color: var(--fg-secondary);
  font-weight: 450;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  scale: calc(0.7 + 0.3 * var(--split) * var(--birth));
  transform-origin: 0 50%;
}
.island-lobe-face.is-error {
  color: var(--danger);
}
.island-lobe-face.is-warning {
  color: var(--warning);
}
.island-row.is-left .island-lobe-clip {
  left: auto;
  right: 0;
  translate: calc(-1 * var(--drop-x)) 0;
  justify-content: flex-end;
}
.island-row.is-left .island-lobe-face {
  transform-origin: 100% 50%;
}

/*
 * The bloup (Gloup.tsx): the island's idle creature, a lobe on the left
 * that is nothing but two light eyes in the black. It is the capsule of
 * the bloup SVG at the lobe's height, so its face is the drawing's own
 * width and nothing else. The eyes ride a group whose transform is set as
 * each glance is chosen; the move is this transition, with the spring's
 * touch of overshoot so a look lands like a saccade. A blink squashes
 * each eye about its own middle: shut fast, open a little slower.
 */
.island-lobe-face.island-bloup {
  padding: 0;
}
.bloup {
  display: block;
  overflow: visible;
}
.bloup-eyes {
  transition: transform 220ms var(--ease-spring);
}
.bloup-eye {
  fill: var(--fg);
  transform-box: fill-box;
  transform-origin: center;
  transition: transform 120ms var(--ease-out);
}
.bloup-eyes.is-blink .bloup-eye {
  transform: scaleY(0.08);
  transition-duration: 60ms;
}
.island-clip {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: inherit;
  transition: background-color var(--duration-fast) var(--ease-out);
}
.island-main:hover .island-clip {
  background: var(--bg-hover);
}
.island.is-alert .island-main:hover .island-clip,
.island.is-expanded .island-main:hover .island-clip {
  background: transparent;
}
/*
 * A face is a zero-width box on the shell's centre line whose content
 * overflows it evenly to both sides, rather than a box translated back by
 * half its width: the face is kept in its own compositing layer (so the
 * crossfade never creates one and drops it, which on Windows would switch
 * the text between grey and ClearType anti-aliasing as it ends), and a
 * composited layer sits on whole pixels — an integer offset and no
 * translate leave it nothing to snap by. DynamicIsland.tsx measures the
 * content, not this box.
 */
.island-face {
  position: absolute;
  top: 0;
  left: 50%;
  width: 0;
  display: flex;
  justify-content: center;
  will-change: transform;
}
.island-face > * {
  flex: none;
}
/*
 * A face comes in soft and small and resolves. The blur is its own, shorter
 * animation on the focus curve: it must reach zero while still moving
 * quickly, or the moment the renderer drops the last fraction of a pixel of
 * blur shows as the text popping sharp (see --ease-focus in tokens.css).
 */
.island-face.is-current {
  animation:
    island-face-in calc(var(--duration-normal) * 1.6) var(--ease-out) 40ms both,
    island-face-focus calc(var(--duration-normal) * 0.8) var(--ease-focus) 40ms both;
}
.island-face.is-leaving {
  pointer-events: none;
  animation: island-face-out var(--duration-normal) var(--ease-out) forwards;
}
@keyframes island-face-in {
  from {
    opacity: 0;
    scale: 0.92;
  }
  to {
    opacity: 1;
    scale: 1;
  }
}
@keyframes island-face-focus {
  from {
    filter: blur(6px);
  }
  to {
    filter: blur(0);
  }
}
@keyframes island-face-out {
  to {
    opacity: 0;
    filter: blur(6px);
    scale: 0.94;
  }
}

/* Compact faces: idle, activity, flash. */
.island-compact {
  display: flex;
  align-items: center;
  gap: 8px;
  height: var(--island-height);
  padding: 0 12px 0 10px;
  color: var(--fg);
  white-space: nowrap;
  font-weight: 500;
  letter-spacing: -0.01em;
}
.island.is-idle .island-compact {
  padding-left: 12px;
}
.island-label {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  min-width: 0;
}
.island-name {
  max-width: 260px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.island-dirty {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--fg-secondary);
  flex-shrink: 0;
}
/* A muted qualifier after a label: a flash's "4.2s", an activity's age. */
.island-detail {
  color: var(--fg-muted);
  font-weight: 450;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.island-detail.is-error {
  color: var(--danger);
}
.island-age {
  min-width: 2.5ch;
  animation: fade-in var(--duration-normal) var(--ease-out) both;
}
/* What a lobe carries. */
.island-readout {
  display: inline-flex;
  align-items: center;
  gap: 3px;
}
.island-pos {
  /* A flex item, so text-align does nothing: centre the text via the flex axis. */
  justify-content: center;
  min-width: 5ch;
}
/* A name that can run long: the branch, a terminal's folder. */
.island-branch,
.island-place {
  max-width: 140px;
  overflow: hidden;
  text-overflow: ellipsis;
}
.island-count {
  display: inline-block;
  min-width: 14px;
  padding: 0 4px;
  margin-left: 2px;
  border-radius: var(--radius-pill);
  background: var(--bg-active);
  color: var(--fg);
  font-size: 10px;
  font-weight: 600;
  line-height: 14px;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* A settled watcher (dev server, --watch): a green dot that blinks as it prints, and its name. */
.island-live {
  gap: 5px;
}

/* ---------- Reduced motion (App.css:3551) ---------- */
@media (prefers-reduced-motion: reduce) {
  .island-orb,
  .island-orb::before,
  .island-dot.is-busy,
  .island-live-dot {
    animation: none;
  }
  .island-ring {
    transition: none;
  }
  .island-lobe,
  .island.is-split .island-lobe {
    transition-delay: 0s;
  }
}
