@brftech/filex-core 0.30.1 → 0.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +37 -2
  2. package/dist/filex-core.js +10571 -8278
  3. package/dist/filex-core.js.map +1 -1
  4. package/dist/filex-core.umd.cjs +95 -87
  5. package/dist/filex-core.umd.cjs.map +1 -1
  6. package/dist/index.d.ts +548 -66
  7. package/dist/style.css +1 -1
  8. package/package.json +1 -1
  9. package/src/FileExplorer.vue +1104 -26
  10. package/src/components/Breadcrumb.vue +4 -2
  11. package/src/components/CommandPalette.vue +18 -2
  12. package/src/components/E2eRecoveryUnlockModal.vue +193 -0
  13. package/src/components/EncryptedFolderModal.vue +10 -0
  14. package/src/components/FilterBar.vue +244 -0
  15. package/src/components/GalleryView.vue +48 -0
  16. package/src/components/GridView.vue +85 -3
  17. package/src/components/InspectorPanel.vue +231 -8
  18. package/src/components/ListView.vue +11 -1
  19. package/src/components/RecoveryKeyModal.vue +133 -0
  20. package/src/components/SecondaryPane.vue +15 -1
  21. package/src/components/SideNav.vue +329 -6
  22. package/src/components/StarButton.vue +27 -15
  23. package/src/components/Toolbar.vue +235 -49
  24. package/src/components/ViewSwitcher.vue +81 -0
  25. package/src/composables/useFileApi.ts +83 -0
  26. package/src/composables/useKeyboardShortcuts.ts +7 -0
  27. package/src/index.ts +33 -1
  28. package/src/lib/e2ecrypto.ts +716 -70
  29. package/src/lib/fileFilters.ts +143 -0
  30. package/src/lib/listing.ts +103 -1
  31. package/src/lib/star.ts +42 -0
  32. package/src/lib/tags.ts +105 -0
  33. package/src/locales/en.ts +154 -2
  34. package/src/locales/tr.ts +154 -2
  35. package/src/modals/PermissionsModal.vue +18 -2
  36. package/src/styles/base.css +743 -0
  37. package/src/types/ExplorerConfig.ts +53 -1
  38. package/src/types/FileNode.ts +23 -0
@@ -542,6 +542,11 @@ filex-explorer {
542
542
  opacity: 0.7;
543
543
  }
544
544
  .fe-grid__thumb {
545
+ /* yildiz:s1 — positioning context for the star chip in the corner. The
546
+ gallery's thumb already had one; this one did not, so an absolutely
547
+ placed chip would have resolved against whatever ancestor happened to be
548
+ positioned (the grid, or the explorer root) and landed in the wrong tile. */
549
+ position: relative;
545
550
  display: flex;
546
551
  align-items: center;
547
552
  justify-content: center;
@@ -3836,6 +3841,197 @@ filex-explorer {
3836
3841
  .fe-e2e-optlink:hover {
3837
3842
  text-decoration: underline;
3838
3843
  }
3844
+
3845
+ /* --- wiring:e2 recovery ---------------------------------------------
3846
+ Unscoped and fe-prefixed on purpose: a scoped <style> in an SFC does not
3847
+ survive the web-component build, so every class a core component uses has
3848
+ to live here. */
3849
+
3850
+ /* The shown-once key. Monospace, big, wrapping — it exists to be read off
3851
+ the screen and typed somewhere else, so legibility beats compactness. */
3852
+ .fe-e2e-rk {
3853
+ display: flex;
3854
+ flex-direction: column;
3855
+ gap: 12px;
3856
+ }
3857
+ .fe-e2e-rk__lead {
3858
+ margin: 0;
3859
+ font-size: 13px;
3860
+ color: var(--fe-text-muted);
3861
+ }
3862
+ .fe-e2e-rk__key {
3863
+ display: block;
3864
+ padding: 12px 14px;
3865
+ border: 1px solid var(--fe-border);
3866
+ border-radius: var(--fe-radius-sm);
3867
+ background: var(--fe-bg-elev);
3868
+ color: var(--fe-text);
3869
+ font-family: var(--fe-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
3870
+ font-size: 15px;
3871
+ letter-spacing: 0.04em;
3872
+ line-height: 1.7;
3873
+ word-break: break-all;
3874
+ user-select: all;
3875
+ text-align: center;
3876
+ }
3877
+ .fe-e2e-rk__actions {
3878
+ display: flex;
3879
+ gap: 8px;
3880
+ }
3881
+ .fe-e2e-rk__escrow {
3882
+ border: 1px solid var(--fe-border);
3883
+ border-left: 3px solid var(--fe-warning, var(--fe-primary));
3884
+ border-radius: var(--fe-radius-sm);
3885
+ padding: 8px 10px;
3886
+ font-size: 12.5px;
3887
+ }
3888
+ .fe-e2e-rk__escrow strong {
3889
+ display: block;
3890
+ margin-bottom: 2px;
3891
+ color: var(--fe-text);
3892
+ }
3893
+ .fe-e2e-rk__escrow p {
3894
+ margin: 0;
3895
+ color: var(--fe-text-muted);
3896
+ }
3897
+ .fe-e2e-rk__kid code {
3898
+ font-size: 11.5px;
3899
+ }
3900
+
3901
+ /* Unlock-without-the-password dialog. */
3902
+ .fe-e2e-recover {
3903
+ display: flex;
3904
+ flex-direction: column;
3905
+ gap: 12px;
3906
+ }
3907
+ .fe-e2e-recover__none {
3908
+ margin: 0;
3909
+ font-size: 13px;
3910
+ color: var(--fe-text-muted);
3911
+ }
3912
+ .fe-e2e-recover__hint {
3913
+ margin: 0;
3914
+ font-size: 12.5px;
3915
+ color: var(--fe-text-muted);
3916
+ }
3917
+ /* Why the escrow key does not apply to THIS folder. Deliberately not muted
3918
+ to the point of invisibility: it is the answer to a question the reader
3919
+ is already asking, and the pre-adoption case has no other surface. */
3920
+ .fe-e2e-recover__note {
3921
+ margin: 0;
3922
+ padding: 8px 10px;
3923
+ font-size: 12.5px;
3924
+ line-height: 1.45;
3925
+ color: var(--fe-text);
3926
+ border: 1px solid var(--fe-border);
3927
+ border-left: 3px solid var(--fe-warning, #f59e0b);
3928
+ border-radius: var(--fe-radius);
3929
+ background: var(--fe-bg-elev);
3930
+ }
3931
+ .fe-e2e-recover__tabs {
3932
+ display: flex;
3933
+ gap: 4px;
3934
+ padding: 3px;
3935
+ border: 1px solid var(--fe-border);
3936
+ border-radius: var(--fe-radius-lg);
3937
+ background: var(--fe-bg-elev);
3938
+ }
3939
+ .fe-e2e-recover__tab {
3940
+ flex: 1;
3941
+ padding: 6px 10px;
3942
+ border: 0;
3943
+ border-radius: calc(var(--fe-radius-lg) - 4px);
3944
+ background: transparent;
3945
+ color: var(--fe-text-muted);
3946
+ font: inherit;
3947
+ font-size: 12.5px;
3948
+ cursor: pointer;
3949
+ }
3950
+ .fe-e2e-recover__tab--on {
3951
+ background: var(--fe-bg);
3952
+ color: var(--fe-text);
3953
+ font-weight: 600;
3954
+ }
3955
+ .fe-e2e-recover__key {
3956
+ font-family: var(--fe-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
3957
+ letter-spacing: 0.04em;
3958
+ text-align: center;
3959
+ }
3960
+ .fe-e2e-recover__escrow {
3961
+ font-family: var(--fe-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
3962
+ font-size: 11.5px;
3963
+ resize: vertical;
3964
+ min-height: 90px;
3965
+ }
3966
+
3967
+ /* The offer to give a pre-recovery folder a recovery key. A strip, not a
3968
+ modal: it must be visible and dismissible, never something that blocks
3969
+ the folder the user came here to open. */
3970
+ .fe-e2e-upgrade {
3971
+ display: flex;
3972
+ align-items: flex-start;
3973
+ justify-content: space-between;
3974
+ gap: 14px;
3975
+ flex-wrap: wrap;
3976
+ margin: 0 0 10px;
3977
+ padding: 10px 12px;
3978
+ border: 1px solid var(--fe-border);
3979
+ border-left: 3px solid var(--fe-primary);
3980
+ border-radius: var(--fe-radius-sm);
3981
+ background: color-mix(in srgb, var(--fe-primary) 6%, transparent);
3982
+ }
3983
+ .fe-e2e-upgrade__text {
3984
+ flex: 1 1 320px;
3985
+ min-width: 0;
3986
+ }
3987
+ .fe-e2e-upgrade__text strong {
3988
+ display: block;
3989
+ font-size: 13px;
3990
+ color: var(--fe-text);
3991
+ }
3992
+ .fe-e2e-upgrade__text p {
3993
+ margin: 4px 0 0;
3994
+ font-size: 12.5px;
3995
+ color: var(--fe-text-muted);
3996
+ }
3997
+ .fe-e2e-upgrade__escrow {
3998
+ color: var(--fe-danger) !important;
3999
+ }
4000
+ .fe-e2e-upgrade__actions {
4001
+ display: flex;
4002
+ gap: 8px;
4003
+ flex: none;
4004
+ }
4005
+ /* wiring:e2 escrow-offer — the same strip, asking a heavier question:
4006
+ accepting hands the operator a permanent second key. Amber rather than
4007
+ the recovery offer's primary tint, so it does not read as routine. */
4008
+ .fe-e2e-upgrade--escrow {
4009
+ border-left-color: var(--fe-warning, #f59e0b);
4010
+ background: color-mix(in srgb, var(--fe-warning, #f59e0b) 7%, transparent);
4011
+ }
4012
+ /* The link to the honest long version has to LOOK like a link: it inherits
4013
+ the warning colour, and without this it read as ordinary sentence text —
4014
+ somebody being asked to hand over a key should be able to see the way to
4015
+ the page that explains what they are handing over. */
4016
+ .fe-e2e-upgrade__escrow a {
4017
+ color: inherit;
4018
+ text-decoration: underline;
4019
+ text-underline-offset: 2px;
4020
+ font-weight: 600;
4021
+ }
4022
+ .fe-e2e-upgrade__escrow a:hover,
4023
+ .fe-e2e-upgrade__escrow a:focus-visible {
4024
+ text-decoration-thickness: 2px;
4025
+ }
4026
+ .fe-e2e-upgrade__pw {
4027
+ display: flex;
4028
+ flex-direction: column;
4029
+ gap: 4px;
4030
+ margin-top: 8px;
4031
+ max-width: 320px;
4032
+ font-size: 12.5px;
4033
+ color: var(--fe-text-muted);
4034
+ }
3839
4035
  /* === /wiring:e2 === */
3840
4036
 
3841
4037
  /* === ui-fix — toolbar tek satır + katlama + ölçüm şeridi ============= */
@@ -4220,6 +4416,106 @@ filex-explorer {
4220
4416
  letter-spacing: 0.02em;
4221
4417
  }
4222
4418
 
4419
+ /* === etiket:t1 — the Tags section ==================================== */
4420
+ /* A tag row is an ordinary panel item; only its label wraps differently,
4421
+ because a tag is user text and can be long. */
4422
+ .fe-sidenav__item--tag .fe-sidenav__text {
4423
+ text-transform: none;
4424
+ }
4425
+ /* "Show all (12)" / "Show fewer" — a link, not a button: it changes what this
4426
+ section shows, it is not a destination. */
4427
+ .fe-sidenav__more {
4428
+ display: block;
4429
+ width: 100%;
4430
+ margin: 2px 0 0;
4431
+ padding: 5px 10px;
4432
+ border: 0;
4433
+ border-radius: 999px;
4434
+ background: transparent;
4435
+ color: var(--fe-primary);
4436
+ font: inherit;
4437
+ font-size: 12.5px;
4438
+ text-align: left;
4439
+ cursor: pointer;
4440
+ }
4441
+ .fe-sidenav__more:hover {
4442
+ background: var(--fe-bg-hover);
4443
+ }
4444
+ .fe-sidenav__more:focus-visible {
4445
+ outline: 2px solid var(--fe-primary);
4446
+ outline-offset: 1px;
4447
+ }
4448
+ /* "No tags yet — add them from a file's menu." */
4449
+ .fe-sidenav__hint {
4450
+ margin: 2px 0 4px;
4451
+ padding: 0 10px;
4452
+ font-size: 11.5px;
4453
+ line-height: 1.45;
4454
+ color: var(--fe-text-muted);
4455
+ }
4456
+
4457
+ /* === yildiz:s1 — the star chip on a grid / gallery tile =============== */
4458
+ /* Positioned by the card, painted by StarButton (.filex-star-btn.is-card).
4459
+ ⚠ The rules live HERE and not in the SFC: the panel's styles do too, and
4460
+ these are about the CARD's geometry, which is this file's business. */
4461
+ .fe-grid__star,
4462
+ .fe-gal__star {
4463
+ position: absolute;
4464
+ top: 6px;
4465
+ right: 6px;
4466
+ z-index: 2;
4467
+ /* Hidden until the tile is hovered or something inside it is focused —
4468
+ EXCEPT when the file is starred, which is the whole point: the mark has
4469
+ to be visible without hovering every tile to find it (see .is-starred
4470
+ below). */
4471
+ opacity: 0;
4472
+ transition: opacity 120ms ease;
4473
+ }
4474
+ .fe-grid__card:hover .fe-grid__star,
4475
+ .fe-grid__card:focus-within .fe-grid__star,
4476
+ .fe-gal__card:hover .fe-gal__star,
4477
+ .fe-gal__card:focus-within .fe-gal__star,
4478
+ .fe-grid__star:focus-within,
4479
+ .fe-gal__star:focus-within,
4480
+ .fe-grid__star:has(.is-starred),
4481
+ .fe-gal__star:has(.is-starred) {
4482
+ opacity: 1;
4483
+ }
4484
+ /* `:has()` is the modern half of the rule above; this is the same thing for
4485
+ engines without it — a starred chip paints itself. Both are needed: the
4486
+ parent wrapper carries the opacity, the child cannot raise it on its own. */
4487
+ .filex-star-btn.is-card.is-starred {
4488
+ opacity: 1;
4489
+ }
4490
+ /* The chip itself: a round translucent puck, legible over a photo thumbnail
4491
+ as well as over a flat icon tile. */
4492
+ .filex-star-btn.is-card {
4493
+ width: 26px;
4494
+ height: 26px;
4495
+ padding: 0;
4496
+ justify-content: center;
4497
+ border-radius: 999px;
4498
+ background: rgba(17, 24, 39, 0.55);
4499
+ color: #fff;
4500
+ backdrop-filter: blur(2px);
4501
+ }
4502
+ .filex-star-btn.is-card:hover {
4503
+ background: rgba(17, 24, 39, 0.78);
4504
+ color: var(--filex-accent-amber, #f59e0b);
4505
+ }
4506
+ .filex-star-btn.is-card.is-starred {
4507
+ color: var(--filex-accent-amber, #f59e0b);
4508
+ }
4509
+ .filex-star-btn.is-card:focus-visible {
4510
+ outline: 2px solid var(--fe-primary);
4511
+ outline-offset: 1px;
4512
+ }
4513
+ /* The gallery's meta strip covers the tile's foot on hover and is
4514
+ aria-hidden; the star sits above it and stays clickable. */
4515
+ .fe-gal__star {
4516
+ z-index: 3;
4517
+ }
4518
+
4223
4519
  /* Narrow (<560px): a drawer over the listing, never a column. At 390px a
4224
4520
  232px column leaves 158px for the files, and a 56px rail still takes an
4225
4521
  eighth of the screen from a listing that is already tight. */
@@ -4370,3 +4666,450 @@ filex-explorer {
4370
4666
  margin-left: auto;
4371
4667
  }
4372
4668
  /* --- /gezinti:g1 --- */
4669
+
4670
+ /* === surucu:d1 — the Drive shell (uiProfile: 'drive', GitHub #14) ======
4671
+ Everything here is additive and gated on a class the other two profiles
4672
+ never carry, so `standard` and `simple` render exactly what they rendered
4673
+ before this block existed.
4674
+
4675
+ ⚠ Unscoped and prefixed, like the rest of this file. A `<style scoped>` in
4676
+ an SFC compiles to `.cls[data-v-HASH]`, and the hash does not match in the
4677
+ web-component build — the rules silently stop applying in every embed, which
4678
+ is how the share dialog once shipped as raw unstyled HTML.
4679
+ ---------------------------------------------------------------------- */
4680
+
4681
+ /* ── the header ───────────────────────────────────────────────────────── */
4682
+ .fe-toolbar--drive {
4683
+ gap: 10px;
4684
+ padding: 8px 12px;
4685
+ }
4686
+ /* The field takes the row. `min-width: 0` because a flex item's default `auto`
4687
+ minimum is its content width and an <input> reports a wide one — without it
4688
+ the header refuses to shrink and the whole explorer grows a horizontal
4689
+ scrollbar at 390px. */
4690
+ .fe-toolbar__search-group--drive {
4691
+ flex: 1 1 auto;
4692
+ min-width: 0;
4693
+ gap: 8px;
4694
+ }
4695
+ .fe-drivesearch {
4696
+ position: relative;
4697
+ display: flex;
4698
+ align-items: center;
4699
+ gap: 8px;
4700
+ flex: 1 1 auto;
4701
+ min-width: 0;
4702
+ max-width: 720px;
4703
+ padding: 0 10px 0 12px;
4704
+ height: 40px;
4705
+ border-radius: 999px;
4706
+ border: 1px solid transparent;
4707
+ background: var(--fe-bg-elev);
4708
+ color: var(--fe-text);
4709
+ }
4710
+ .fe-drivesearch:focus-within {
4711
+ background: var(--fe-bg);
4712
+ border-color: var(--fe-border-strong);
4713
+ box-shadow: var(--fe-shadow-sm);
4714
+ }
4715
+ .fe-drivesearch__glass {
4716
+ flex: 0 0 auto;
4717
+ width: 18px;
4718
+ height: 18px;
4719
+ color: var(--fe-text-muted);
4720
+ }
4721
+ .fe-drivesearch__input {
4722
+ flex: 1 1 auto;
4723
+ min-width: 0;
4724
+ border: 0;
4725
+ background: transparent;
4726
+ color: inherit;
4727
+ font: inherit;
4728
+ font-size: 14px;
4729
+ outline: none;
4730
+ }
4731
+ .fe-drivesearch__input::placeholder {
4732
+ color: var(--fe-text-muted);
4733
+ }
4734
+ /* The ⌘K chip. A real button, not decoration: it is the one visible door to
4735
+ the palette in this shell, so it has to be clickable and tab-reachable —
4736
+ printing a shortcut nobody can press with a mouse is a hint, not a control. */
4737
+ .fe-drivesearch__kbd {
4738
+ flex: 0 0 auto;
4739
+ padding: 3px 8px;
4740
+ border: 1px solid var(--fe-border);
4741
+ border-radius: var(--fe-radius-sm);
4742
+ background: var(--fe-bg);
4743
+ color: var(--fe-text-muted);
4744
+ font: inherit;
4745
+ font-size: 11.5px;
4746
+ letter-spacing: 0.02em;
4747
+ cursor: pointer;
4748
+ white-space: nowrap;
4749
+ }
4750
+ .fe-drivesearch__kbd:hover {
4751
+ color: var(--fe-text);
4752
+ border-color: var(--fe-border-strong);
4753
+ }
4754
+ .fe-drivesearch__kbd:focus-visible {
4755
+ outline: 2px solid var(--fe-primary);
4756
+ outline-offset: 1px;
4757
+ }
4758
+
4759
+ /* ── the "+ New" button ───────────────────────────────────────────────── */
4760
+ .fe-sidenav__new {
4761
+ display: inline-flex;
4762
+ align-items: center;
4763
+ gap: 10px;
4764
+ width: 100%;
4765
+ padding: 11px 18px;
4766
+ border-radius: 999px;
4767
+ border: 1px solid var(--fe-primary);
4768
+ background: var(--fe-primary);
4769
+ color: var(--fe-text-on-primary);
4770
+ font: inherit;
4771
+ font-size: 14px;
4772
+ font-weight: 600;
4773
+ text-align: left;
4774
+ white-space: nowrap;
4775
+ overflow: hidden;
4776
+ cursor: pointer;
4777
+ box-shadow: var(--fe-shadow-sm);
4778
+ }
4779
+ .fe-sidenav__new:hover {
4780
+ background: var(--fe-primary-hover);
4781
+ border-color: var(--fe-primary-hover);
4782
+ }
4783
+ .fe-sidenav__new:focus-visible {
4784
+ outline: 2px solid var(--fe-primary);
4785
+ outline-offset: 2px;
4786
+ }
4787
+ .fe-sidenav__new .fe-ficon {
4788
+ width: 20px;
4789
+ height: 20px;
4790
+ flex: 0 0 auto;
4791
+ }
4792
+ /* On the rail it becomes a circle: a pill with no label is a stretched blob. */
4793
+ .fe-sidenav--rail .fe-sidenav__new {
4794
+ width: 40px;
4795
+ height: 40px;
4796
+ padding: 0;
4797
+ justify-content: center;
4798
+ border-radius: 50%;
4799
+ }
4800
+
4801
+ /* ── the storage line ─────────────────────────────────────────────────── */
4802
+ .fe-sidenav__quota {
4803
+ flex: 0 0 auto;
4804
+ padding: 10px 12px 12px;
4805
+ border-top: 1px solid var(--fe-border);
4806
+ }
4807
+ .fe-sidenav--rail .fe-sidenav__quota {
4808
+ padding: 10px 8px;
4809
+ }
4810
+ .fe-sidenav__quota-label {
4811
+ margin: 0 0 6px;
4812
+ font-size: 11px;
4813
+ font-weight: 600;
4814
+ letter-spacing: 0.04em;
4815
+ text-transform: uppercase;
4816
+ color: var(--fe-text-muted);
4817
+ }
4818
+ .fe-sidenav__quota-bar {
4819
+ height: 5px;
4820
+ border-radius: 999px;
4821
+ background: var(--fe-bg-hover);
4822
+ overflow: hidden;
4823
+ }
4824
+ .fe-sidenav__quota-fill {
4825
+ display: block;
4826
+ height: 100%;
4827
+ border-radius: 999px;
4828
+ background: var(--fe-primary);
4829
+ transition: width 0.2s ease;
4830
+ }
4831
+ .fe-sidenav__quota-text {
4832
+ margin: 6px 0 0;
4833
+ font-size: 12px;
4834
+ color: var(--fe-text-muted);
4835
+ }
4836
+
4837
+ /* ── the breadcrumb row ───────────────────────────────────────────────── */
4838
+ /* Not a drive shell: the wrapper leaves layout entirely, so the breadcrumb is
4839
+ the same flex child of .fe__primary it has always been. */
4840
+ .fe-subhead--plain {
4841
+ display: contents;
4842
+ }
4843
+ .fe-subhead {
4844
+ display: flex;
4845
+ align-items: center;
4846
+ gap: 8px;
4847
+ min-width: 0;
4848
+ }
4849
+ .fe-subhead > .fe-breadcrumb {
4850
+ flex: 1 1 auto;
4851
+ min-width: 0;
4852
+ }
4853
+ .fe-subhead__actions {
4854
+ flex: 0 0 auto;
4855
+ display: flex;
4856
+ align-items: center;
4857
+ gap: 6px;
4858
+ padding-right: 8px;
4859
+ }
4860
+
4861
+ /* ── the filter row ───────────────────────────────────────────────────── */
4862
+ .fe-filterbar {
4863
+ flex: 0 0 auto;
4864
+ display: flex;
4865
+ align-items: center;
4866
+ gap: 8px;
4867
+ padding: 8px 10px;
4868
+ /* Scrolls sideways ON ITSELF at 390px rather than widening the explorer:
4869
+ three chips and a clear button do not fit a phone, and the alternative is
4870
+ a horizontal scrollbar on everything. */
4871
+ overflow-x: auto;
4872
+ overflow-y: hidden;
4873
+ scrollbar-width: none;
4874
+ }
4875
+ .fe-filterbar::-webkit-scrollbar {
4876
+ display: none;
4877
+ }
4878
+ .fe-filterbar__chip {
4879
+ flex: 0 0 auto;
4880
+ display: inline-flex;
4881
+ align-items: center;
4882
+ gap: 4px;
4883
+ height: 32px;
4884
+ padding: 0 10px 0 12px;
4885
+ border: 1px solid var(--fe-border-strong);
4886
+ border-radius: 999px;
4887
+ background: transparent;
4888
+ color: var(--fe-text);
4889
+ font: inherit;
4890
+ font-size: 13px;
4891
+ cursor: pointer;
4892
+ white-space: nowrap;
4893
+ }
4894
+ .fe-filterbar__chip:hover {
4895
+ background: var(--fe-bg-hover);
4896
+ }
4897
+ .fe-filterbar__chip.is-set {
4898
+ background: var(--fe-bg-selected);
4899
+ border-color: var(--fe-primary);
4900
+ font-weight: 600;
4901
+ }
4902
+ .fe-filterbar__chip.is-open {
4903
+ border-color: var(--fe-primary);
4904
+ }
4905
+ .fe-filterbar__chip:focus-visible {
4906
+ outline: 2px solid var(--fe-primary);
4907
+ outline-offset: 1px;
4908
+ }
4909
+ .fe-filterbar__caret {
4910
+ width: 15px;
4911
+ height: 15px;
4912
+ }
4913
+ .fe-filterbar__clear {
4914
+ flex: 0 0 auto;
4915
+ border: 0;
4916
+ background: transparent;
4917
+ color: var(--fe-primary);
4918
+ font: inherit;
4919
+ font-size: 12.5px;
4920
+ cursor: pointer;
4921
+ padding: 4px 6px;
4922
+ border-radius: var(--fe-radius-sm);
4923
+ white-space: nowrap;
4924
+ }
4925
+ .fe-filterbar__clear:hover {
4926
+ background: var(--fe-bg-hover);
4927
+ }
4928
+ .fe-filterbar__count {
4929
+ flex: 0 0 auto;
4930
+ margin-left: auto;
4931
+ padding-left: 8px;
4932
+ font-size: 12px;
4933
+ color: var(--fe-text-muted);
4934
+ white-space: nowrap;
4935
+ }
4936
+ /* Teleported to <body>: z-index 90, the layer the context menus already use.
4937
+ The onboarding tour sits above at 96 on purpose — a tour step must never end
4938
+ up behind a filter popover. */
4939
+ .fe-filterpop {
4940
+ position: fixed;
4941
+ z-index: 90;
4942
+ min-width: 190px;
4943
+ max-height: 60vh;
4944
+ overflow-y: auto;
4945
+ padding: 6px;
4946
+ border: 1px solid var(--fe-border);
4947
+ border-radius: var(--fe-radius-md);
4948
+ background: var(--fe-bg);
4949
+ color: var(--fe-text);
4950
+ box-shadow: var(--fe-shadow);
4951
+ font-family: var(--fe-font);
4952
+ }
4953
+ .fe-filterpop__item {
4954
+ display: flex;
4955
+ align-items: center;
4956
+ gap: 8px;
4957
+ width: 100%;
4958
+ padding: 7px 10px;
4959
+ border: 0;
4960
+ border-radius: var(--fe-radius-sm);
4961
+ background: transparent;
4962
+ color: inherit;
4963
+ font: inherit;
4964
+ font-size: 13px;
4965
+ text-align: left;
4966
+ cursor: pointer;
4967
+ }
4968
+ .fe-filterpop__item:hover {
4969
+ background: var(--fe-bg-hover);
4970
+ }
4971
+ .fe-filterpop__item:focus-visible {
4972
+ outline: 2px solid var(--fe-primary);
4973
+ outline-offset: -2px;
4974
+ }
4975
+ .fe-filterpop__tick {
4976
+ flex: 0 0 14px;
4977
+ color: var(--fe-primary);
4978
+ font-size: 12px;
4979
+ }
4980
+
4981
+ /* ── Folders / Files sections in the grid ─────────────────────────────── */
4982
+ /* A grid item spanning every column, so the cards keep flowing under it. */
4983
+ .fe-grid__heading {
4984
+ grid-column: 1 / -1;
4985
+ margin: 6px 2px 2px;
4986
+ font-size: 13px;
4987
+ font-weight: 600;
4988
+ color: var(--fe-text);
4989
+ }
4990
+ .fe-grid__heading:first-child {
4991
+ margin-top: 0;
4992
+ }
4993
+
4994
+ /* ── the details panel: tabs, people, link row ────────────────────────── */
4995
+ .fe-inspector__tabs {
4996
+ flex: 0 0 auto;
4997
+ display: flex;
4998
+ gap: 2px;
4999
+ padding: 0 10px;
5000
+ border-bottom: 1px solid var(--fe-border);
5001
+ }
5002
+ .fe-inspector__tab {
5003
+ padding: 9px 12px;
5004
+ border: 0;
5005
+ border-bottom: 2px solid transparent;
5006
+ background: transparent;
5007
+ color: var(--fe-text-muted);
5008
+ font: inherit;
5009
+ font-size: 13px;
5010
+ cursor: pointer;
5011
+ }
5012
+ .fe-inspector__tab:hover {
5013
+ color: var(--fe-text);
5014
+ }
5015
+ .fe-inspector__tab.is-active {
5016
+ color: var(--fe-primary);
5017
+ border-bottom-color: var(--fe-primary);
5018
+ font-weight: 600;
5019
+ }
5020
+ .fe-inspector__tab:focus-visible {
5021
+ outline: 2px solid var(--fe-primary);
5022
+ outline-offset: -2px;
5023
+ }
5024
+ .fe-inspector__people {
5025
+ list-style: none;
5026
+ margin: 0 0 8px;
5027
+ padding: 0;
5028
+ display: flex;
5029
+ flex-direction: column;
5030
+ gap: 8px;
5031
+ }
5032
+ .fe-inspector__person {
5033
+ display: flex;
5034
+ align-items: center;
5035
+ gap: 10px;
5036
+ min-width: 0;
5037
+ }
5038
+ .fe-inspector__avatar {
5039
+ flex: 0 0 28px;
5040
+ width: 28px;
5041
+ height: 28px;
5042
+ border-radius: 50%;
5043
+ display: inline-flex;
5044
+ align-items: center;
5045
+ justify-content: center;
5046
+ background: var(--fe-primary);
5047
+ color: var(--fe-text-on-primary);
5048
+ font-size: 12px;
5049
+ font-weight: 600;
5050
+ }
5051
+ .fe-inspector__person-main {
5052
+ display: flex;
5053
+ flex-direction: column;
5054
+ min-width: 0;
5055
+ }
5056
+ .fe-inspector__person-name {
5057
+ font-size: 13px;
5058
+ overflow: hidden;
5059
+ text-overflow: ellipsis;
5060
+ white-space: nowrap;
5061
+ }
5062
+ .fe-inspector__person-sub {
5063
+ font-size: 11.5px;
5064
+ color: var(--fe-text-muted);
5065
+ }
5066
+ .fe-inspector__linkrow {
5067
+ display: flex;
5068
+ align-items: center;
5069
+ gap: 8px;
5070
+ }
5071
+ .fe-inspector__linkicon {
5072
+ flex: 0 0 auto;
5073
+ font-size: 14px;
5074
+ }
5075
+ .fe-inspector__linknone {
5076
+ flex: 1 1 auto;
5077
+ min-width: 0;
5078
+ font-size: 13px;
5079
+ color: var(--fe-text-muted);
5080
+ }
5081
+ .fe-inspector__hint {
5082
+ margin: 6px 0 0;
5083
+ font-size: 12px;
5084
+ color: var(--fe-text-muted);
5085
+ }
5086
+
5087
+ /* ── narrow ───────────────────────────────────────────────────────────── */
5088
+ /* At 390px the chip is the only thing that has to go: the shortcut it prints
5089
+ cannot be typed on a phone anyway, and the palette stays reachable from the
5090
+ "⋯" menu. The field keeps the whole row. */
5091
+ .fe--narrow .fe-drivesearch__kbd {
5092
+ display: none;
5093
+ }
5094
+ .fe--narrow .fe-drivesearch {
5095
+ height: 36px;
5096
+ max-width: none;
5097
+ }
5098
+ .fe--narrow .fe-subhead__actions {
5099
+ padding-right: 4px;
5100
+ }
5101
+ .fe--narrow .fe-filterbar {
5102
+ padding: 6px 8px;
5103
+ }
5104
+ /* The narrow DRIVE header is three items: toggle · field · "⋯". The field is
5105
+ the only one that grows, and `min-width: 0` is what lets it shrink past its
5106
+ own content width — without it the row is wider than the phone. */
5107
+ .fe-toolbar--narrow.fe-toolbar--drive {
5108
+ gap: 6px;
5109
+ padding: 6px 8px;
5110
+ }
5111
+ .fe-toolbar--narrow .fe-drivesearch {
5112
+ flex: 1 1 auto;
5113
+ min-width: 0;
5114
+ }
5115
+ /* === /surucu:d1 === */